# Copyright 2012-2020 Meson development team

# 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.

"""Representations specific to the arm family of compilers."""

import os
import typing as T

from ... import mesonlib
from ...linkers import ArmClangDynamicLinker
from ...mesonlib import OptionKey
from ..compilers import clike_debug_args
from .clang import clang_color_args

if T.TYPE_CHECKING:
    from ...environment import Environment
    from ...compilers.compilers import Compiler
else:
    # This is a bit clever, for mypy we pretend that these mixins descend from
    # Compiler, so we get all of the methods and attributes defined for us, but
    # for runtime we make them descend from object (which all classes normally
    # do). This gives up DRYer type checking, with no runtime impact
    Compiler = object

arm_buildtype_args = {
    'plain': [],
    'debug': [],
    'debugoptimized': [],
    'release': [],
    'minsize': [],
    'custom': [],
}  # type: T.Dict[str, T.List[str]]

arm_optimization_args = {
    '0': ['-O0'],
    'g': ['-g'],
    '1': ['-O1'],
    '2': [], # Compiler defaults to -O2
    '3': ['-O3', '-Otime'],
    's': ['-O3'], # Compiler defaults to -Ospace
}  # type: T.Dict[str, T.List[str]]

armclang_buildtype_args = {
    'plain': [],
    'debug': [],
    'debugoptimized': [],
    'release': [],
    'minsize': [],
    'custom': [],
}  # type: T.Dict[str, T.List[str]]

armclang_optimization_args = {
    '0': [], # Compiler defaults to -O0
    'g': ['-g'],
    '1': ['-O1'],
    '2': ['-O2'],
    '3': ['-O3'],
    's': ['-Oz']
}  # type: T.Dict[str, T.List[str]]


class ArmCompiler(Compiler):

    """Functionality that is common to all ARM family compilers."""

    def __init__(self) -> None:
        if not self.is_cross:
            raise mesonlib.EnvironmentException('armcc supports only cross-compilation.')
        self.id = 'arm'
        default_warn_args = []  # type: T.List[str]
        self.warn_args = {'0': [],
                          '1': default_warn_args,
                          '2': default_warn_args + [],
                          '3': default_warn_args + []}  # type: T.Dict[str, T.List[str]]
        # Assembly
        self.can_compile_suffixes.add('s')

    def get_pic_args(self) -> T.List[str]:
        # FIXME: Add /ropi, /rwpi, /fpic etc. qualifiers to --apcs
        return []

    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
        return arm_buildtype_args[buildtype]

    # Override CCompiler.get_always_args
    def get_always_args(self) -> T.List[str]:
        return []

    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
        return ['--depend_target', outtarget, '--depend', outfile, '--depend_single_line']

    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
        # FIXME: Add required arguments
        # NOTE from armcc user guide:
        # "Support for Precompiled Header (PCH) files is deprecated from ARM Compiler 5.05
        # onwards on all platforms. Note that ARM Compiler on Windows 8 never supported
        # PCH files."
        return []

    def get_pch_suffix(self) -> str:
        # NOTE from armcc user guide:
        # "Support for Precompiled Header (PCH) files is deprecated from ARM Compiler 5.05
        # onwards on all platforms. Note that ARM Compiler on Windows 8 never supported
        # PCH files."
        return 'pch'

    def thread_flags(self, env: 'Environment') -> T.List[str]:
        return []

    def get_coverage_args(self) -> T.List[str]:
        return []

    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
        return arm_optimization_args[optimization_level]

    def get_debug_args(self, is_debug: bool) -> T.List[str]:
        return clike_debug_args[is_debug]

    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
        for idx, i in enumerate(parameter_list):
            if i[:2] == '-I' or i[:2] == '-L':
                parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))

        return parameter_list


class ArmclangCompiler(Compiler):

    def __init__(self) -> None:
        if not self.is_cross:
            raise mesonlib.EnvironmentException('armclang supports only cross-compilation.')
        # Check whether 'armlink' is available in path
        if not isinstance(self.linker, ArmClangDynamicLinker):
            raise mesonlib.EnvironmentException(f'Unsupported Linker {self.linker.exelist}, must be armlink')
        if not mesonlib.version_compare(self.version, '==' + self.linker.version):
            raise mesonlib.EnvironmentException('armlink version does not match with compiler version')
        self.id = 'armclang'
        self.base_options = {
            OptionKey(o) for o in
            ['b_pch', 'b_lto', 'b_pgo', 'b_sanitize', 'b_coverage',
             'b_ndebug', 'b_staticpic', 'b_colorout']}
        # Assembly
        self.can_compile_suffixes.add('s')

    def get_pic_args(self) -> T.List[str]:
        # PIC support is not enabled by default for ARM,
        # if users want to use it, they need to add the required arguments explicitly
        return []

    def get_colorout_args(self, colortype: str) -> T.List[str]:
        return clang_color_args[colortype][:]

    def get_buildtype_args(self, buildtype: str) -> T.List[str]:
        return armclang_buildtype_args[buildtype]

    def get_pch_suffix(self) -> str:
        return 'gch'

    def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
        # Workaround for Clang bug http://llvm.org/bugs/show_bug.cgi?id=15136
        # This flag is internal to Clang (or at least not documented on the man page)
        # so it might change semantics at any time.
        return ['-include-pch', os.path.join(pch_dir, self.get_pch_name(header))]

    def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
        return ['-MD', '-MT', outtarget, '-MF', outfile]

    def get_optimization_args(self, optimization_level: str) -> T.List[str]:
        return armclang_optimization_args[optimization_level]

    def get_debug_args(self, is_debug: bool) -> T.List[str]:
        return clike_debug_args[is_debug]

    def compute_parameters_with_absolute_paths(self, parameter_list: T.List[str], build_dir: str) -> T.List[str]:
        for idx, i in enumerate(parameter_list):
            if i[:2] == '-I' or i[:2] == '-L':
                parameter_list[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))

        return parameter_list
