#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#
# Copyright (c) 2024 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import os
import re
import sys
import stat
import subprocess
import csv
from concurrent.futures import ThreadPoolExecutor

from datetime import datetime
from distutils.spawn import find_executable
from containers.arg import Arg
from containers.status import throw_exception
from exceptions.ohos_exception import OHOSException
from modules.interface.build_module_interface import BuildModuleInterface
from resources.config import Config
from resources.global_var import CURRENT_OHOS_ROOT, DEFAULT_BUILD_ARGS
from resolver.interface.args_resolver_interface import ArgsResolverInterface
from util.type_check_util import TypeCheckUtil
from util.io_util import IoUtil
from util.log_util import LogUtil
from util.system_util import SystemUtil
from util.type_check_util import TypeCheckUtil
from util.component_util import ComponentUtil
from util.product_util import ProductUtil
from util.prebuild.patch_process import Patch
from util.post_build.part_rom_statistics import output_part_rom_status


def rename_file(source_file, target_file):
    try:
        os.rename(source_file, target_file)
    except FileNotFoundError as rename_error:
        LogUtil.hb_warning(rename_error)


class BuildArgsResolver(ArgsResolverInterface):

    def __init__(self, args_dict: dict):
        super().__init__(args_dict)

    @staticmethod
    def resolve_product(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--product-name' arg.
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        config = Config()
        target_generator = build_module.target_generator
        target_generator.regist_arg('product_name', config.product)

        target_generator.regist_arg('target_cpu', config.target_cpu)
        target_generator.regist_arg('target_os', config.target_os)
        target_generator.regist_arg('precise_branch', config.precise_branch)
        target_generator.regist_arg(
            'is_{}_system'.format(config.os_level), True)
        if config.compile_mode == 'host':
            target_generator.regist_arg('use_musl', False)
            if config.target_os == 'linux':
                host_toolchain_cpu = config.target_cpu
                if host_toolchain_cpu == 'x86_64':
                    host_toolchain_cpu = 'x64'
                target_generator.regist_arg(
                    'custom_toolchain',
                    f'//build/toolchain/linux:clang_{host_toolchain_cpu}')
        else:
            target_generator.regist_arg('product_path', config.product_path) 
            target_generator.regist_arg( 
                'product_config_path', config.product_config_path)

            target_generator.regist_arg('device_name', config.board)
            target_generator.regist_arg('device_path', config.device_path)
            target_generator.regist_arg('device_company', config.device_company)
            target_generator.regist_arg(
                'device_config_path', config.device_config_path)
            target_generator.regist_arg('ohos_kernel_type', config.kernel)
            target_generator.regist_arg('ohos_build_compiler_specified',
                                        ProductUtil.get_compiler(config.device_path))

        target_generator.regist_arg('ohos_build_time',
                                    SystemUtil.get_current_time(time_type='timestamp'))
        target_generator.regist_arg('ohos_build_datetime',
                                    SystemUtil.get_current_time(time_type='datetime'))

        features_dict = ProductUtil.get_features_dict(config.product_json)
        for key, value in features_dict.items():
            target_generator.regist_arg(key, value)

        if config.compile_mode != 'host' and ProductUtil.get_compiler(config.device_path) == 'clang':
            target_generator.regist_arg(
                'ohos_build_compiler_dir', config.clang_path)

        if target_arg.arg_value == 'ohos-sdk':
            target_generator = build_module.target_generator
            target_generator.regist_arg('build_ohos_sdk', True)
            target_generator.regist_arg('build_ohos_ndk', True)
            target_generator.regist_arg('enable_enhanced_opt', False)
            if len(build_module.args_dict['build_target'].arg_value) == 0:
                build_module.args_dict['build_target'].arg_value = [
                    'build_ohos_sdk']
            build_module.args_dict['target_cpu'].arg_value = 'arm64'
        elif target_arg.arg_value == 'arkui-x':
            target_generator = build_module.target_generator
            target_generator.regist_arg('is_arkui_x', True)
            target_generator.regist_arg('enable_ng_build', True)
            target_generator.regist_arg('is_component_build', False)
            target_generator.regist_arg('use_musl', False)
            target_generator.regist_arg('is_use_check_deps', False)
            if len(build_module.args_dict['build_target'].arg_value) == 0:
                build_module.args_dict['build_target'].arg_value = [
                    'arkui_targets']

    @staticmethod
    def resolve_target_cpu(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--target-cpu' arg.
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        config = Config()
        default_build_args = IoUtil.read_json_file(DEFAULT_BUILD_ARGS)
        if config.target_cpu == "":
            config.target_cpu = target_arg.arg_value
        elif target_arg.arg_value != default_build_args.get("target_cpu").get("argDefault"):
            config.target_cpu = target_arg.arg_value

    @staticmethod
    def resolve_target_os(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--target-os' arg.
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        config = Config()
        default_build_args = IoUtil.read_json_file(DEFAULT_BUILD_ARGS)
        if config.target_os == "":
            config.target_os = target_arg.arg_value
        elif target_arg.arg_value != default_build_args.get("target_os").get("argDefault"):
            config.target_os = target_arg.arg_value

    @staticmethod
    def resolve_precise_branch(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--precise-branch' arg.
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        config = Config()
        default_build_args = IoUtil.read_json_file(DEFAULT_BUILD_ARGS)
        if config.precise_branch == "":
            config.precise_branch = target_arg.arg_value
        elif target_arg.arg_value != default_build_args.get("precise_branch").get("argDefault"):
            config.precise_branch = target_arg.arg_value

    @staticmethod
    def get_tdd_repository(input_file):
        if not os.path.isfile(input_file):
            raise OHOSException(f'{input_file} not found')
        config = Config()
        target_set = set()
        with open(input_file, 'r') as input_f:
            data = csv.DictReader(input_f)
            for csv_row in data:
                if csv_row.get(config.precise_branch) == 'Y' or csv_row.get('dayu200_tdd') == 'Y':
                    target_set.add(csv_row['repoistory'])
        return target_set

    @staticmethod
    def is_self_build(target, build_module: BuildModuleInterface):
        change_info_file = 'change_info.json'
        if not os.path.exists(change_info_file):
            return True
        change_info = IoUtil.read_json_file(change_info_file)
        change_files = []
        file_operations = {
            "added": lambda x: x,
            "rename": lambda x: [item for pair in x for item in pair],
            "modified": lambda x: x,
            "deleted": lambda x: x
        }
        
        for value in change_info.values():
            if value.get("name") != target:
                continue
            changed_files = value.get("changed_file_list", {})
            for op, processor in file_operations.items():
                if op not in changed_files:
                    continue
                if any("include" in f or "interface" in f for f in processor(changed_files[op])):
                    print(processor(changed_files[op]))
                    return False
        return True

    @staticmethod
    def get_tdd_build_target(build_target_arg, build_module: BuildModuleInterface):
        parts_file = os.path.join(CURRENT_OHOS_ROOT, 'test/testfwk/developer_test/precise_compilation/part_tdd.json')
        tdd_manifest_file = os.path.join(CURRENT_OHOS_ROOT, '.repo/manifests/matrix_product.csv')
        parts_data = IoUtil.read_json_file(parts_file)
        repository_set = BuildArgsResolver.get_tdd_repository(tdd_manifest_file)
        config = Config()
        prefix = 'out/{}/build_configs/'.format(config.product)
        target_name = build_target_arg[len('TDD'):]
        build_targets = []
        for target in target_name.split(','):
            if target not in repository_set:
                print('{} not find in csv!'.format(target))
                continue
            for item in parts_data:
                if item['name'] == target:
                    new_targets = ([prefix + test_target for test_target in item['selfTarget'].split(',')]
                                   if BuildArgsResolver.is_self_build(target, build_module)
                                   else [prefix + test_target for test_target in item['buildTarget'].split(',')])
                    build_targets.extend(new_targets)
                    break
            else:
                build_targets = ['build/ohos/packages:build_all_test_pkg']
                target_generator = build_module.target_generator
                target_generator.regist_arg('use_thin_lto', False)
                break
        return build_targets

    @staticmethod
    def get_target(target):
        if target.startswith("//"):
            return target[2:]
        else:
            return target

    @staticmethod
    def get_precise_build_target(precise_target_file, build_module: BuildModuleInterface):
        try:
            with open(precise_target_file, 'r') as file:
                lines = file.readlines()
        
            cleaned_lines = []
            for line in lines:
                stripped_line = line.strip()
                if stripped_line:
                    cleaned_lines.append(BuildArgsResolver.get_target(stripped_line))
        
            build_target = ','.join(cleaned_lines)
            return cleaned_lines
    
        except Exception as e:
            print(f"file error: {e}")
            return ""

    @staticmethod
    @throw_exception
    def resolve_build_target(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--build-target' arg.
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        :raise OHOSException: when build target not exist in compiling product.
        """
        config = Config()
        build_executor = build_module.target_compiler
        target_list = []
        test_target_list = ['build_all_test_pkg', 'package_testcase', 'package_testcase_mlf']
        if "precise_module_build" in target_arg.arg_value:
            precise_build_target = [ "precise" ]

        if len(target_arg.arg_value):
            for target_name in target_arg.arg_value:
                if target_name.endswith('make_test') or target_name.split(':')[-1] in test_target_list:
                    target_generator = build_module.target_generator
                    target_generator.regist_arg('use_thin_lto', False)
                    target_list.append(target_name)
                elif target_name.startswith('TDD'):
                    target_list.extend(BuildArgsResolver.get_tdd_build_target(target_name, build_module))
                elif target_name == "precise_module_build":
                    target_list.extend(precise_build_target)
                else:
                    target_list.append(target_name)
        else:
            if os.getcwd() == CURRENT_OHOS_ROOT:
                target_list = ['images']
            elif ComponentUtil.is_in_component_dir(os.getcwd()) and \
                    ComponentUtil.is_component_in_product(
                    ComponentUtil.get_component_name(os.getcwd()), Config().product):
                component_name = ComponentUtil.get_component_name(os.getcwd())
                LogUtil.write_log(Config().log_path, 'In the component "{}" directory,'
                                  'this compilation will compile only this component'.format(
                                      component_name),
                                  'warning')
                target_list.append(component_name)
                target_list.append(component_name + '_test')
            else:
                component_name = ComponentUtil.get_component_name(os.getcwd())
                component_name = os.path.basename(
                    os.getcwd()) if component_name == '' else component_name
                raise OHOSException('There is no target component "{}" for the current product "{}"'
                                    .format(component_name, Config().product), "4001")
        build_executor.regist_arg('build_target', target_list)

    @staticmethod
    def resolve_rename_last_log(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--rename-last-log' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        if target_arg.arg_value:
            config = Config()
            out_path = config.out_path
            logfile = os.path.join(out_path, 'build.log')
            if os.path.exists(logfile):
                mtime = os.stat(logfile).st_mtime
                rename_file(logfile, '{}/build.{}.log'.format(out_path, mtime))

    @staticmethod
    def resolve_log_mode(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--log-mode' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module: build module object which is used to get other services.
        :phase: prebuild.
        """
        if target_arg.arg_value:
            config = Config()
            config.log_mode = target_arg.arg_value

    @staticmethod
    def resolve_ccache(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--ccache' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        if target_arg.arg_value:
            config = Config()
            ccache_path = find_executable('ccache')
            if ccache_path is None:
                LogUtil.hb_warning('Failed to find ccache, ccache disabled.')
                return
            else:
                target_generator = build_module.target_generator
                target_generator.regist_arg(
                    'ohos_build_enable_ccache', target_arg.arg_value)

            ccache_local_dir = os.environ.get('CCACHE_LOCAL_DIR')
            ccache_base = os.environ.get('CCACHE_BASE')
            if not ccache_local_dir:
                ccache_local_dir = '.ccache'
            if not ccache_base:
                ccache_base = os.environ.get('HOME')
            ccache_base = os.path.join(ccache_base, ccache_local_dir)
            if not os.path.exists(ccache_base):
                os.makedirs(ccache_base, exist_ok=True)

            ccache_log_suffix = os.environ.get('CCACHE_LOG_SUFFIX')
            if ccache_log_suffix:
                logfile = os.path.join(
                    ccache_base, "ccache.{}.log".format(ccache_log_suffix))
            elif os.environ.get('CCACHE_LOGFILE'):
                logfile = os.environ.get('CCACHE_LOGFILE')
                if not os.path.exists(os.path.dirname(logfile)):
                    os.makedirs(os.path.dirname(logfile), exist_ok=True)
            else:
                logfile = os.path.join(ccache_base, "ccache.log")
            if os.path.exists(logfile):
                oldfile = '{}.old'.format(logfile)
                if os.path.exists(oldfile):
                    os.unlink(oldfile)
                rename_file(logfile, oldfile)

            os.environ['CCACHE_EXEC'] = ccache_path
            os.environ['CCACHE_LOGFILE'] = logfile
            os.environ['USE_CCACHE'] = '1'
            os.environ['CCACHE_DIR'] = ccache_base
            os.environ['CCACHE_UMASK'] = '002'
            os.environ['CCACHE_BASEDIR'] = config.root_path
            ccache_max_size = os.environ.get('CCACHE_MAXSIZE')
            if not ccache_max_size:
                ccache_max_size = '100G'

            cmd = ['ccache', '-M', ccache_max_size]

            SystemUtil.exec_command(cmd, log_path=config.log_path)

    @staticmethod
    def resolve_xcache(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--xcache' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        if target_arg.arg_value:
            config = Config()
            xcache_path = "/opt/buildtools/nextbuild/xcache"
            if not os.path.exists(xcache_path):
                LogUtil.hb_warning('Failed to find xcache, xcache disabled.')
                return
            else:
                target_generator = build_module.target_generator
                target_generator.regist_arg(
                    'ohos_build_enable_xcache', target_arg.arg_value)
                os.environ['XCACHE_EXEC'] = xcache_path
                os.environ['USE_XCACHE'] = '1'

    @staticmethod
    def resolve_pycache(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--enable-pycache' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        if target_arg.arg_value:
            config = Config()
            pycache_dir = os.environ.get('CCACHE_BASE')
            # The default value is HOME for local users
            if not pycache_dir:
                pycache_dir = os.environ.get('HOME')
            pycache_dir = os.path.join(pycache_dir, '.pycache')
            os.environ['PYCACHE_DIR'] = pycache_dir
            pyd_start_cmd = [
                'python3',
                '{}/build/scripts/util/pyd.py'.format(config.root_path),
                '--root',
                pycache_dir,
                '--start',
            ]
            cmd = ['/bin/bash', '-c', ' '.join(pyd_start_cmd), '&']
            subprocess.Popen(cmd)

    @staticmethod
    def resolve_full_compilation(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--full-compilation' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        if target_arg.arg_value:
            build_executor = build_module.target_compiler
            target_list = build_executor.args_dict.get('build_target', None)
            if isinstance(target_list, list):
                target_list.append('make_all')
                target_list.append('make_test')
            else:
                build_executor.regist_arg(
                    'build_target', ['make_all', 'make_test'])
            target_generator = build_module.target_generator
            target_generator.regist_arg('use_thin_lto', False)

    @staticmethod
    @throw_exception
    def resolve_gn_args(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--gn-args' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        :raise OHOSException: when some gn_arg is not in 'key=value' format.
        """
        target_generator = build_module.target_generator
        target_generator.regist_arg(
            'device_type', build_module.args_dict['device_type'].arg_value)
        target_generator.regist_arg(
            'build_variant', build_module.args_dict['build_variant'].arg_value)
        if target_generator.args_dict['product_name'] == 'rk3568' and not build_module.loader.args_dict['build_xts']:
            target_generator.regist_arg('ohos_components_checktype', 4)
            target_generator.regist_arg('ohos_interception_rule_switch', 1023)
            
        for gn_args in target_arg.arg_value:
            try:
                gn_args_list = gn_args.split()
                for gn_arg in gn_args_list:
                    variable, value = gn_arg.split('=')
                    if TypeCheckUtil.is_bool_type(value):
                        if str(value).lower() == 'false':
                            convert_value = False
                        elif str(value).lower() == 'true':
                            convert_value = True
                    elif TypeCheckUtil.is_int_type(value):
                        convert_value = int(value)
                    elif isinstance(value, list):
                        convert_value = list(value)
                    else:
                        convert_value = str(value).strip('"')
                    target_generator.regist_arg(variable, convert_value)
            except ValueError:
                raise OHOSException(f'Invalid gn args: {gn_arg}', "0001")

    @staticmethod
    @throw_exception
    def resolve_gn_flags(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--gn-flags' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: targetGenerate.
        :raise OHOSException: when some gn_arg is not in 'key=value' format.
        """
        target_generator = build_module.target_generator
        gn_flags_list = []
        for gn_flags in target_arg.arg_value:
            gn_flags = re.sub("'", "", gn_flags)
            gn_flags_list.append(gn_flags)
        target_generator.regist_flag('gn_flags', gn_flags_list)

    @staticmethod
    @throw_exception
    def resolve_ninja_args(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--ninja-args' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: prebuild.
        :raise OHOSException: when the value of the ninja parameter does not use quotation marks.
        """
        build_executor = build_module.target_compiler
        ninja_args_list = []
        for ninja_arg in target_arg.arg_value:
            ninja_arg = re.sub("'", "", ninja_arg)
            ninja_args_list.append(ninja_arg)
        build_executor.regist_arg('ninja_args', ninja_args_list)

    @staticmethod
    @throw_exception
    def resolve_prebuilts_sdk_gn_args(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--prebuilts-sdk-gn-args' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [unused]: build module object which is used to get other services.
        :phase: prebuild.
        """
        normalized_args = []
        for arg in target_arg.arg_value:
            if not isinstance(arg, str):
                continue
            item = arg.strip().strip("'").strip('"')
            if not item:
                continue
            if '=' not in item:
                raise OHOSException(f"Invalid prebuilts-sdk-gn-args: '{arg}', expect key=value", "0001")
            normalized_args.append(item)

        target_arg.arg_value = normalized_args
        return
    
    @staticmethod
    @throw_exception
    def resolve_strict_mode(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--strict-mode' arg.
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: load.
        :raise OHOSException: when preloader or loader results not correct
        """
        if target_arg.arg_value:
            preloader = build_module.preloader
            loader = build_module.loader
            if not preloader.outputs.check_outputs():
                raise OHOSException('Preloader result not correct', "1001")
            if not loader.outputs.check_outputs():
                raise OHOSException('Loader result not correct ', "2001")

    @staticmethod
    def resolve_scalable_build(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--scalable-build' arg.
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: load.
        """
        loader = build_module.loader
        loader.regist_arg("scalable_build", target_arg.arg_value)

    @staticmethod
    def resolve_build_example(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--build-example' arg.
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: load.
        """
        loader = build_module.loader
        loader.regist_arg("build_example", target_arg.arg_value)

    @staticmethod
    def resolve_build_platform_name(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '---build-platform-name' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: load.
        """
        loader = build_module.loader
        loader.regist_arg("build_platform_name", target_arg.arg_value)

    @staticmethod
    def resolve_build_xts(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--build-xts' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: load.
        """
        loader = build_module.loader
        loader.regist_arg("build_xts", target_arg.arg_value)
        for gn_arg in build_module.args_dict['gn_args'].arg_value:
            if 'pr_path_list' in gn_arg:
                build_module.args_dict['gn_args'].arg_value.append("precise_xts=true")
                config = Config()
                variable, value = gn_arg.split('=')
                pyd_start_cmd = [
                    'python3',
                    '{}/test/xts/acts/get_dependency.py'.format(config.root_path),
                    value,
                ]
                subprocess.call(pyd_start_cmd)
            if 'build_xts' in gn_arg:
                variable, value = gn_arg.split('=')
                if str(value).lower() == 'false':
                    value = False
                elif str(value).lower() == 'true':
                    value = True
                loader.regist_arg(variable, value)

    @staticmethod
    def resolve_ignore_api_check(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--ignore-api-check' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: load.
        """
        loader = build_module.loader
        if len(target_arg.arg_value):
            loader.regist_arg("ignore_api_check", target_arg.arg_value)
        else:
            loader.regist_arg("ignore_api_check", [
                              'xts', 'common', 'testfwk'])

    @staticmethod
    def resolve_load_test_config(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--load-test-config' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: load.
        """
        loader = build_module.loader
        loader.regist_arg("load_test_config", target_arg.arg_value)

    @staticmethod
    @throw_exception
    def resolve_export_para(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--export-para' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: targetGenerate.
        """
        target_generator = build_module.target_generator
        for gn_arg in target_arg.arg_value:
            try:
                variable, value = gn_arg.split(':')
                if TypeCheckUtil.is_bool_type(value):
                    if str(value).lower() == 'false':
                        value = False
                    elif str(value).lower() == 'true':
                        value = True
                elif TypeCheckUtil.is_int_type(value):
                    value = int(value)
                else:
                    value = str(value)
                target_generator.regist_arg(variable, value)
            except ValueError:
                raise OHOSException(f'Invalid gn args: {gn_arg}', "0001")

    @staticmethod
    def resolve_log_level(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--log-level' arg.
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: targetGenerate.
        """
        if target_arg.arg_value == 'debug':
            target_generator = build_module.target_generator
            target_compiler = build_module.target_compiler
            target_generator.regist_flag('-v', ''),
            target_generator.regist_flag(
                '--tracelog', '{}/gn_trace.log'.format(Config().out_path))
            target_generator.regist_flag('--ide', 'json')
            target_compiler.regist_arg('-v', '')

    @staticmethod
    @throw_exception
    def resolve_test(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--test' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: targetGenerate.
        """
        if len(target_arg.arg_value) > 1:
            target_generator = build_module.target_generator
            # TODO: Ask sternly why the xts subsystem passes parameters in this way?
            if 'notest' in target_arg.arg_value:
                target_generator.regist_arg('ohos_test_args', 'notest')
            elif 'xts' in target_arg.arg_value:
                test_target_index = 1
                if target_arg.arg_value.index('xts') == 1:
                    test_target_index = 0
                target_generator.regist_arg(
                    'ohos_xts_test_args', target_arg.arg_value[test_target_index])
            else:
                raise OHOSException('Test type value "{}" is not support'
                                    .format(target_arg.arg_value), "0002")

    @staticmethod
    def resolve_build_type(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--build-type' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: targetGenerate.
        """
        target_generator = build_module.target_generator
        if target_arg.arg_value == 'debug':
            target_generator.regist_arg('is_debug', True)
        elif target_arg.arg_value == 'profile':
            target_generator.regist_arg('is_profile', True)
        # For historical reasons, this value must be debug
        target_generator.regist_arg('ohos_build_type', 'debug')

    @staticmethod
    def resolve_root_perf_main(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--root-perf-main' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: targetGenerate.
        """
        target_generator = build_module.target_generator
        target_generator.regist_arg('root_perf_main', target_arg.arg_value)

    @staticmethod
    def resolve_runtime_mode(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--runtime-mode' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: targetGenerate.
        """
        target_generator = build_module.target_generator
        target_generator.regist_arg('runtime_mode', target_arg.arg_value)
        
    @staticmethod
    def resolve_keep_ninja_going(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--keep-ninja-going' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: targetCompilation.
        """
        if target_arg.arg_value:
            target_compiler = build_module.target_compiler
            target_compiler.regist_arg('-k1000000', '')

    @staticmethod
    def resolve_build_variant(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--build-variant' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetCompilation.
        """
        pass

    @staticmethod
    def resolve_device_type(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--device-type' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetCompilation.
        """
        config = Config()
        ohos_para_data = []
        ohos_para_file_path = os.path.join(
            config.out_path, 'packages/phone/system/etc/param/ohos.para')
        if target_arg.arg_value != 'default':
            with os.fdopen(os.open(ohos_para_file_path,
                                   os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR),
                           'r', encoding='utf-8') as ohos_para_file:
                for line in ohos_para_file:
                    ohos_para_data.append(line)
            for i, line in enumerate(ohos_para_data):
                if ohos_para_data[i].__contains__('const.build.characteristics'):
                    ohos_para_data[i] = 'const.build.characteristics=' + \
                        target_arg.arg_value + '\n'
                    break
            data = ''
            for line in ohos_para_data:
                data += line
            with os.fdopen(os.open(ohos_para_file_path,
                                   os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR),
                           'w', encoding='utf-8') as ohos_para_file:
                ohos_para_file.write(data)

    @staticmethod
    def resolve_archive_image(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--archive-image' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetCompilation
        """
        if target_arg.arg_value:
            config = Config()
            image_path = os.path.join(
                config.out_path, 'packages', 'phone', 'images')
            if os.path.exists(image_path):
                packaged_file_path = os.path.join(
                    config.out_path, 'images.tar.gz')
                cmd = ['tar', '-zcvf', packaged_file_path, image_path]
                SystemUtil.exec_command(cmd, log_path=config.out_path)
            else:
                LogUtil.hb_info(
                    '"--archive-image" option not work, cause the currently compiled product is not a standard product')

    @staticmethod
    def resolve_patch(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--patch' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetCompilation
        """
        if target_arg.arg_value:
            patch_obj = Patch()
            patch_obj.patch_make()

    @staticmethod
    def resolve_rom_size_statistics(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--rom-size-statistics' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetCompilation
        """
        if target_arg.arg_value:
            output_part_rom_status(CURRENT_OHOS_ROOT)

    @staticmethod
    def resolve_stat_ccache(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve "--stat-ccache' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetCompilation
        """
        if target_arg.arg_value:
            config = Config()
            ccache_path = find_executable('ccache')
            if ccache_path is None:
                LogUtil.hb_warning('Failed to find ccache, ccache disabled.')
                return
            ccache_log_suffix = os.environ.get('CCACHE_LOG_SUFFIX')
            if ccache_log_suffix:
                logfile = "ccache.{}.log".format(ccache_log_suffix)
            else:
                logfile = "ccache.log"
            ccache_local_dir = os.environ.get('CCACHE_LOCAL_DIR')
            if not ccache_local_dir:
                ccache_local_dir = '.ccache'
            ccache_base = os.environ.get('CCACHE_BASE')

            # The default value is HOME for local users
            if not ccache_base:
                ccache_base = os.environ.get('HOME')
            ccache_base = os.path.join(ccache_base, ccache_local_dir)
            if os.environ.get('CCACHE_LOGFILE'):
                logfile = os.environ.get('CCACHE_LOGFILE')
            else:
                logfile = os.path.join(ccache_base, logfile)
            cmd = [
                'python3', '{}/build/scripts/summary_ccache_hitrate.py'.format(
                    config.root_path), logfile
            ]
            if os.path.isfile(logfile):
                SystemUtil.exec_command(cmd, log_path=config.log_path, log_stage="[POSTBUILD]")

    @staticmethod
    def resolve_get_warning_list(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve "--get-warning-list' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetCompilation
        """
        if target_arg.arg_value:
            config = Config()
            cmd = [
                'python3',
                '{}/build/scripts/get_warnings.py'.format(config.root_path),
                '--build-log-file',
                '{}/build.log'.format(config.out_path),
                '--warning-out-file',
                '{}/packages/WarningList.txt'.format(config.out_path),
            ]
            SystemUtil.exec_command(cmd, log_path=config.log_path, log_stage="[POSTBUILD]")

    @staticmethod
    def resolve_generate_ninja_trace(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve "--generate-ninja-trace' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetCompilation
        """
        if target_arg.arg_value:
            config = Config()
            # 中国标准时间与UTC标准时间差8h, _start_time记录为中国标准时间
            epoch = datetime.utcfromtimestamp(28800)
            unixtime = '%f' % (
                (build_module.target_compiler._start_time - epoch).total_seconds() * 10**9)
            cmd = [
                'python3',
                '{}/build/scripts/ninja2trace.py'.format(config.root_path),
                '--ninja-log',
                '{}/.ninja_log'.format(config.out_path),
                "--trace-file",
                "{}/build.trace".format(config.out_path),
                "--ninja-start-time",
                str(unixtime),
                "--duration-file",
                "{}/sorted_action_duration.txt".format(config.out_path),
            ]
            SystemUtil.exec_command(cmd, log_path=config.log_path, log_stage="[POSTBUILD]")

    @staticmethod
    def resolve_compute_overlap_rate(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve "--compute-overlap-rate' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetCompilation
        """
        if target_arg.arg_value:
            config = Config()
            subsystem_config_overlay_path = os.path.join(config.product_path,
                                                         'subsystem_config_overlay.json')
            if os.path.isfile(subsystem_config_overlay_path):
                cmd = [
                    'python3',
                    '{}/build/ohos/statistics/build_overlap_statistics.py'.format(
                        config.root_path), "--build-out-dir", config.out_path,
                    "--subsystem-config-file",
                    "{}/build/subsystem_config.json".format(config.root_path),
                    "--subsystem-config-overlay-file",
                    "{}/subsystem_config_overlay.json".format(
                        config.product_path),
                    "--root-source-dir", config.root_path
                ]
            else:
                cmd = [
                    'python3',
                    '{}/build/ohos/statistics/build_overlap_statistics.py'.format(
                        config.root_path), "--build-out-dir", config.out_path,
                    "--subsystem-config-file",
                    "{}/build/subsystem_config.json".format(config.root_path),
                    "--root-source-dir", config.root_path
                ]
            SystemUtil.exec_command(cmd, log_path=config.log_path, log_stage="[POSTBUILD]")

    @staticmethod
    def resolve_deps_guard(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--deps-guard' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postbuild
        """
        if target_arg.arg_value:
            config = Config()
            if config.os_level == "standard" and config.compile_mode != 'host':
                sys.path.append(os.path.join(
                    config.root_path, "developtools/integration_verification/tools/deps_guard"))
                from deps_guard import deps_guard
                deps_guard(config.out_path, config.target_cpu)

    @staticmethod
    def resolve_skip_partlist_check(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--skip-partlist-check' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: load.
        """
        loader = build_module.loader
        loader.regist_arg("skip_partlist_check", target_arg.arg_value)

    @staticmethod
    def resolve_enable_scan_optimization(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--enable-scan-optimization' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: load.
        """
        loader = build_module.loader
        loader.regist_arg("enable_scan_optimization", target_arg.arg_value)

    @staticmethod
    def resolve_clean_args(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--clean-args' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postbuild
        """
        if target_arg.arg_value:
            Arg.clean_args_file()

    @staticmethod
    def resolve_sbom(target_arg: Arg, build_module: BuildModuleInterface):
        """resolve '--sbom' arg
        :param target_arg: arg object which is used to get arg value.
        :param build_module [maybe unused]: build module object which is used to get other services.
        :phase: postTargetGenerate.
        """
        if target_arg.arg_value:
            config = Config()
            cmd = [
                'python3',
                '{}/build/ohos/sbom/generate_sbom.py'.format(
                    config.root_path),
                "--source-root-dir", config.root_path,
                "--out-dir", config.out_path,
                "--product", config.product,
                "--platform", config.platform
            ]
            executor = ThreadPoolExecutor(max_workers=1)
            executor.submit(SystemUtil.exec_command, cmd, log_path=config.log_path, log_stage='[postTargetGenerate]')
            executor.shutdown(wait=False)

    # PlaceHolder
    @staticmethod
    def resolve_compiler(target_arg: Arg, build_module: BuildModuleInterface):
        return

    # PlaceHolder
    @staticmethod
    def resolve_jobs(target_arg: Arg, build_module: BuildModuleInterface):
        return

    # PlaceHolder
    @staticmethod
    def resolve_disable_part_of_post_build(target_arg: Arg, build_module: BuildModuleInterface):
        return

    # PlaceHolder
    @staticmethod
    def resolve_disable_package_image(target_arg: Arg, build_module: BuildModuleInterface):
        return

    # PlaceHolder
    @staticmethod
    def resolve_disable_post_build(target_arg: Arg, build_module: BuildModuleInterface):
        return

    # PlaceHolder
    @staticmethod
    def resolve_build_only_load(target_arg: Arg, build_module: BuildModuleInterface):
        return

    # PlaceHolder
    @staticmethod
    def resolve_build_only_gn(target_arg: Arg, build_module: BuildModuleInterface):
        return

    # PlaceHolder
    @staticmethod
    def resolve_fast_rebuild(target_arg: Arg, build_module: BuildModuleInterface):
        return

    # PlaceHolder
    @staticmethod
    def resolve_no_prebuilt_sdk(target_arg: Arg, build_module: BuildModuleInterface):
        return
    
    # PlaceHolder
    @staticmethod
    def resolve_prebuilt_sdk(target_arg: Arg, build_module: BuildModuleInterface):
        return