_sdk_dir := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))

_global_build_variables := \
  LOCAL_NAME \
  LOCAL_INCLUDE_DIRS \
  LOCAL_SRC_C \
  LOCAL_SRC_CPP \
  LOCAL_CFLAGS \
  LOCAL_LDFLAGS \
  LOCAL_CPPFLAGS \
  LOCAL_UUID \
  LOCAL_TARGETS \
  LOCAL_TRUSTLET_EMULATOR \
  LOCAL_LINK_EMULATOR_GP_CLIENT \
  LOCAL_LINK_GP_TEE \
  LOCAL_IMPRINT_TOOL \
  LOCAL_QSEE_PRIVILEGES \
  LOCAL_QSEE_ACCEPT_BUFFER_SIZE \
  LOCAL_API_LEVEL \
  LOCAL_GROUP_ID \
  LOCAL_DRIVER_ID \
  LOCAL_FIPS_CRYPTO \
  LOCAL_CUSTOM_LIBS \
  LOCAL_STATIC_LIBRARIES \
  LOCAL_EXPORT_INCLUDE_DIRS \
  LOCAL_EXPORT_CFLAGS \
  LOCAL_EXPORT_CPPFLAGS \
  LOCAL_EXPORT_LIBRARY \
  LOCAL_HEAP_SIZE_INIT \
  LOCAL_HEAP_SIZE_MAX \
  LOCAL_OUT \
  LOCAL_MEMTYPE \
  LOCAL_NUM_OF_THREAD \
  LOCAL_SERVICE_TYPE \
  LOCAL_INSTANCES \
  LOCAL_SIGN_FLAGS \
  LOCAL_TARGET_SHARED_LIBRARIES \
  LOCAL_TARGET_LINK_GP_CLIENT_API \
  LOCAL_INTERFACE_VERSION \
  LOCAL_SHRINK_PROTOCOL_BUFFER \
  LOCAL_QSEE_DISABLE_INTERNAL_LISTENER \
  LOCAL_QSEE_SYSTEM_APP \
  LOCAL_SYSTEM_APP \
  $(foreach _var,$(modules-LOCALS),LOCAL_$(_var))

include $(_sdk_dir)/target.mk

# Save all variables listed in _global_build_variables into global context.
# Also target-specific and platform-specific variables are searched by suffix.
#   _global_saved_LOCAL_CFLAGS := $(LOCAL_CFLAGS)
#   _global_saved_LOCAL_CFLAGS-<target> := $(LOCAL_CFLAGS-<target>)
#   _global_saved_LOCAL_CFLAGS-<platform> := $(LOCAL_CFLAGS-<platform>)
#   _global_saved_LOCAL_CFLAGS-<target>-<platform> := $(LOCAL_CFLAGS-<target>-<platform>)
save-all-build-variables = \
  $(foreach _var,$(_global_build_variables), \
    $(eval _global_saved_$(_var) := $($(_var))) \
    \
    $(foreach _target,$(_global_target_names), \
      $(eval _global_saved_$(_var)-$(_target) := $($(_var)-$(_target)))) \
    \
    $(foreach _platform,$(_global_target_supported_platforms:,=), \
      $(eval _global_saved_$(_var)-$(_platform) := $($(_var)-$(_platform)))) \
    \
    $(foreach _target,$(_global_target_names), \
      $(foreach _platform,$(_global_target_supported_platforms:,=), \
        $(eval _global_saved_$(_var)-$(_target)-$(_platform) := $($(_var)-$(_target)-$(_platform))))))

# Restore all variables listed in _global_build_variables from global context.
# Target name and platform name is used to handle target-specific parameters for particular  build.
#   LOCAL_CFLAGS := $(_global_saved_LOCAL_NAME)
#   LOCAL_CFLAGS += $(_global_saved_LOCAL_NAME-<target>)
#   LOCAL_CFLAGS += $(_global_saved_LOCAL_NAME-<platform>)
#   LOCAL_CFLAGS += $(_global_saved_LOCAL_NAME-<target>-<platform>)
#
# Skip adding trailing spaces if variables with suffixes are absent.
# Don't use $(strip) because it could remove "good" trailing spaces implicitly.
# Use ":=" instead of "+=" to not add leading space.
#
# $(1) - current target name
# $(2) - current platform name (blowfish, tbase, qsee, etc.)
restore-all-build-variables = \
  $(foreach _var,$(_global_build_variables), \
    $(eval _saved_var := $(_global_saved_$(_var))) \
    $(eval _target_var := $(_global_saved_$(_var)-$(1))) \
    $(eval _platform_var := $(_global_saved_$(_var)-$(2))) \
    $(eval _target_platform_var := $(_global_saved_$(_var)-$(1)-$(2))) \
    \
    $(eval $(_var) := $(_saved_var)) \
    $(if $(_target_var), $(eval $(_var) := $($(_var)) $(_target_var))) \
    $(if $(_platform_var), $(eval $(_var) := $($(_var)) $(_platform_var))) \
    $(if $(_target_platform_var), $(eval $(_var) := $($(_var)) $(_target_platform_var))))

# Clear all variables listed in _global_build_variables in global context.
clear-all-build-variables = \
  $(foreach _var,$(_global_build_variables), \
    $(eval _global_saved_$(_var) :=))

# The main loop to build each target and platform.
build-for-each-target = \
  $(if $(_global_target_names), \
    , \
    $(error Any target configuration is defined. Please, add at least one of by include $$(ADD_TARGET).)) \
  \
  $(call save-all-build-variables) \
  \
  $(foreach _target,$(_global_target_names), \
    $(foreach _platform,$(_global_target_$(_target)_platforms), \
      $(eval $(call -local-target-build,$(_target),$(_platform),$(1))))) \
  \
  $(call clear-all-build-variables)

# The main loop to sign each target and platform.
# $(1) - sign type suffix
sign-for-each-target = \
  $(if $(_global_target_names), \
    , \
    $(error Any target configuration is defined. Please, add at least one of by include $$(ADD_TARGET).)) \
  \
  $(call save-all-build-variables) \
  \
  $(foreach _target,$(_global_target_names), \
    $(foreach _platform,$(_global_target_$(_target)_platforms), \
      $(eval $(call -local-target-sign,$(_target),$(_platform))))) \
  \
  $(call clear-all-build-variables)

# The main loop to export prebuilt binaries for all the platforms.
prebuilt-for-each-target = \
  $(if $(_global_target_names), \
    , \
    $(error Any target configuration is defined. Please, add at least one of by include $$(ADD_TARGET).)) \
  \
  $(call save-all-build-variables) \
  \
  $(foreach _target,$(_global_target_names), \
    $(foreach _platform,$(_global_target_$(_target)_platforms), \
      $(eval $(call -local-target-prebuilt,$(_target),$(_platform))))) \
  \
  $(call clear-all-build-variables)

# The below routine sets _local_platform and _local_suffix to "dummy" if
# platform from $(1) is not found in set of platform from $(2). If the set
# of platform is empty, any platform is allowed.
-restrict-targets = \
  $(if $(strip $(2)),\
    $(if $(filter $(1),$(2)),\
      $(info Target $(1) allowed!),\
      $(eval _local_platform := dummy)\
      $(eval _local_suffix := dummy)\
    ),\
  )

# $(1) - target name
# $(2) - platform name (blowfish, tbase, qsee, etc.)
# $(3) - build file suffix
define -local-target-build
  $(eval LOCAL_TARGET_NAME := $(1))
  $(eval LOCAL_PLATFORM := $(2))

  $(call restore-all-target-parameters,$(1),$(2))
  $(call restore-all-build-variables,$(1),$(2))

  $(eval _local_platform := $(2))
  $(eval _local_suffix := $(3))
  $(call -restrict-targets,$(LOCAL_TARGET_NAME),$(LOCAL_TARGETS))

  $(eval LOCAL_INCLUDE_DIRS += $(call get-target-parameter,$(1),$(2),LOCAL_EXPORT_INCLUDE_DIRS))
  $(eval LOCAL_CFLAGS += $(call get-target-parameter,$(1),$(2),LOCAL_EXPORT_CFLAGS))
  $(eval LOCAL_CPPFLAGS += $(call get-target-parameter,$(1),$(2),LOCAL_EXPORT_CPPFLAGS))

  include $(_sdk_dir)/build-$(_local_platform)-$(_local_suffix).mk
endef

# $(1) - target name
# $(2) - platform name (blowfish, tbase, qsee, etc.)
# $(3) - sign type suffix (none by default if LOCAL_SIGN_TYPE is not specified)
define -local-target-sign
  $(eval LOCAL_TARGET_NAME := $(1))
  $(eval LOCAL_PLATFORM := $(2))

  $(call restore-all-target-parameters,$(1),$(2))
  $(call restore-all-build-variables,$(1),$(2))

  $(eval LOCAL_BOARD := $(LOCAL_SIGN_BOARD))
  $(eval LOCAL_MODEL := $(LOCAL_SIGN_MODEL))
  $(eval LOCAL_RUNTYPE := $(LOCAL_SIGN_RUNTYPE))
  $(eval LOCAL_SIGN_TYPE := $(strip $(LOCAL_SIGN_TYPE)))

  $(eval _local_platform := $(2))
  $(eval _local_suffix := $(if $(LOCAL_SIGN_TYPE),\
    $(LOCAL_SIGN_TYPE),\
    none))

  $(call -restrict-targets,$(LOCAL_TARGET_NAME),$(LOCAL_TARGETS))

  include $(_sdk_dir)/sign-$(_local_platform)-$(_local_suffix).mk
endef

# $(1) - target name
# $(2) - platform name (blowfish, tbase, qsee, etc.)
define -local-target-prebuilt
  $(eval LOCAL_TARGET_NAME := $(1))
  $(eval LOCAL_PLATFORM := $(2))

  $(call restore-all-target-parameters,$(1),$(2))
  $(call restore-all-build-variables,$(1),$(2))

  $(call -restrict-targets,$(LOCAL_TARGET_NAME),$(LOCAL_TARGETS))

  include $(_sdk_dir)/prebuilt-static-library.mk
endef

