# The purpose of this file is to provide search mechanism for locating Zephyr in-work-tree package
# even when they are not installed into CMake package system
# Linux/MacOS: ~/.cmake/packages
# Windows:     Registry database

# Relative directory of workspace project dir as seen from Zephyr package file
set(WORKSPACE_RELATIVE_DIR "../../../../..")

# Relative directory of Zephyr dir as seen from Zephyr package file
set(ZEPHYR_RELATIVE_DIR "../../../..")

# This function updates Zephyr_DIR to the point to the candidate dir.
# For Zephyr 3.0 and earlier, the Zephyr_DIR might in some cases be
# `Zephyr_DIR-NOTFOUND` or pointing to the Zephyr package including the
# boilerplate code instead of the Zephyr package of the included boilerplate.
# This code ensures that when Zephyr releases <=3.0 is loaded, then Zephyr_DIR
# will point correctly, see also #43094 which relates to this.
function(set_zephyr_dir zephyr_candidate)
  get_filename_component(zephyr_candidate_dir "${zephyr_candidate}" DIRECTORY)
  if(NOT "${zephyr_candidate_dir}" STREQUAL "${Zephyr_DIR}")
    set(Zephyr_DIR ${zephyr_candidate_dir} CACHE PATH
        "The directory containing a CMake configuration file for Zephyr." FORCE
    )
  endif()
endfunction()

# This macro returns a list of parent folders to use for later searches.
macro(get_search_paths START_PATH SEARCH_PATHS PREFERENCE_LIST)
  get_filename_component(SEARCH_PATH ${START_PATH} DIRECTORY)
  while(NOT (SEARCH_PATH STREQUAL SEARCH_PATH_PREV))
    foreach(preference ${PREFERENCE_LIST})
      list(APPEND SEARCH_PATHS ${SEARCH_PATH}/${preference})
    endforeach()
    list(APPEND SEARCH_PATHS ${SEARCH_PATH}/zephyr)
    list(APPEND SEARCH_PATHS ${SEARCH_PATH})
    set(SEARCH_PATH_PREV ${SEARCH_PATH})
    get_filename_component(SEARCH_PATH ${SEARCH_PATH} DIRECTORY)
  endwhile()
endmacro()

# This macro can check for additional Zephyr package that has a better match
# Options:
# - ZEPHYR_BASE                : Use the specified ZEPHYR_BASE directly.
# - WORKSPACE_DIR              : Search for projects in specified  workspace.
# - SEARCH_PARENTS             : Search parent folder of current source file (application)
#                                to locate in-project-tree Zephyr candidates.
# - CHECK_ONLY                 : Only set PACKAGE_VERSION_COMPATIBLE to false if a better candidate
#                                is found, default is to also include the found candidate.
# - VERSION_CHECK              : This is the version check stage by CMake find package
# - CANDIDATES_PREFERENCE_LIST : List of candidate to be preferred, if installed
macro(check_zephyr_package)
  set(options CHECK_ONLY SEARCH_PARENTS VERSION_CHECK)
  set(single_args WORKSPACE_DIR ZEPHYR_BASE)
  set(list_args CANDIDATES_PREFERENCE_LIST)
  cmake_parse_arguments(CHECK_ZEPHYR_PACKAGE "${options}" "${single_args}" "${list_args}" ${ARGN})

  if(CHECK_ZEPHYR_PACKAGE_ZEPHYR_BASE)
    set(SEARCH_SETTINGS PATHS ${CHECK_ZEPHYR_PACKAGE_ZEPHYR_BASE} NO_DEFAULT_PATH)
  endif()

  if(CHECK_ZEPHYR_PACKAGE_WORKSPACE_DIR)
    set(SEARCH_SETTINGS PATHS ${CHECK_ZEPHYR_PACKAGE_WORKSPACE_DIR}/zephyr ${CHECK_ZEPHYR_PACKAGE_WORKSPACE_DIR} NO_DEFAULT_PATH)
  endif()

  if(CHECK_ZEPHYR_PACKAGE_SEARCH_PARENTS)
    get_search_paths(${CMAKE_CURRENT_SOURCE_DIR} SEARCH_PATHS "${CHECK_ZEPHYR_PACKAGE_CANDIDATES_PREFERENCE_LIST}")
    set(SEARCH_SETTINGS PATHS ${SEARCH_PATHS} NO_DEFAULT_PATH)
  endif()

  # Searching for version zero means there will be no match, but we obtain
  # a list of all potential Zephyr candidates in the tree to consider.
  find_package(Zephyr 0.0.0 EXACT QUIET ${SEARCH_SETTINGS})

  # The find package will also find ourself when searching using installed candidates.
  # So avoid re-including unless NO_DEFAULT_PATH is set.
  # NO_DEFAULT_PATH means explicit search and we could be part of a preference list.
  if(NOT (NO_DEFAULT_PATH IN_LIST SEARCH_SETTINGS))
    list(REMOVE_ITEM Zephyr_CONSIDERED_CONFIGS ${CMAKE_CURRENT_LIST_DIR}/ZephyrConfig.cmake)
  endif()
  list(REMOVE_DUPLICATES Zephyr_CONSIDERED_CONFIGS)

  foreach(ZEPHYR_CANDIDATE ${Zephyr_CONSIDERED_CONFIGS})
    if(CHECK_ZEPHYR_PACKAGE_WORKSPACE_DIR)
      # Check is done in Zephyr workspace already, thus check only for pure Zephyr candidates.
      get_filename_component(CANDIDATE_DIR ${ZEPHYR_CANDIDATE}/${ZEPHYR_RELATIVE_DIR} ABSOLUTE)
    else()
      get_filename_component(CANDIDATE_DIR ${ZEPHYR_CANDIDATE}/${WORKSPACE_RELATIVE_DIR} ABSOLUTE)
    endif()

    if(CHECK_ZEPHYR_PACKAGE_ZEPHYR_BASE)
        if(CHECK_ZEPHYR_PACKAGE_VERSION_CHECK)
          string(REGEX REPLACE "\.cmake$" "Version.cmake" ZEPHYR_VERSION_CANDIDATE ${ZEPHYR_CANDIDATE})
          include(${ZEPHYR_VERSION_CANDIDATE} NO_POLICY_SCOPE)
          return()
        else()
          include(${ZEPHYR_CANDIDATE} NO_POLICY_SCOPE)
          set_zephyr_dir(${ZEPHYR_CANDIDATE})
          return()
        endif()
    endif()

    string(FIND "${CMAKE_CURRENT_SOURCE_DIR}" "${CANDIDATE_DIR}/" COMMON_INDEX)
    if (COMMON_INDEX EQUAL 0)
      if(CHECK_ZEPHYR_PACKAGE_CHECK_ONLY)
        # A better candidate exists, thus return
        set(PACKAGE_VERSION_COMPATIBLE FALSE)
        return()
      elseif(ZEPHYR_CANDIDATE STREQUAL ${CMAKE_CURRENT_LIST_DIR}/ZephyrConfig.cmake)
        # Current Zephyr is preferred one, let's just break the loop and continue processing.
        break()
      else()
        if(CHECK_ZEPHYR_PACKAGE_VERSION_CHECK)
          string(REGEX REPLACE "\.cmake$" "Version.cmake" ZEPHYR_VERSION_CANDIDATE ${ZEPHYR_CANDIDATE})
          include(${ZEPHYR_VERSION_CANDIDATE} NO_POLICY_SCOPE)
          return()
	else()
          include(${ZEPHYR_CANDIDATE} NO_POLICY_SCOPE)
          set_zephyr_dir(${ZEPHYR_CANDIDATE})
	  return()
        endif()
      endif()
    endif()
  endforeach()
endmacro()
