# Copyright 2019 The 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.

"""Abstractions for the Elbrus family of compilers."""

import os
import typing as T
import subprocess
import re

from .gnu import GnuLikeCompiler
from .gnu import gnu_optimization_args
from ...mesonlib import Popen_safe, OptionKey

if T.TYPE_CHECKING:
    from ...environment import Environment
    from ...coredata import KeyedOptionDictType


class ElbrusCompiler(GnuLikeCompiler):
    # Elbrus compiler is nearly like GCC, but does not support
    # PCH, LTO, sanitizers and color output as of version 1.21.x.

    def __init__(self) -> None:
        super().__init__()
        self.id = 'lcc'
        self.base_options = {OptionKey(o) for o in ['b_pgo', 'b_coverage', 'b_ndebug', 'b_staticpic', 'b_lundef', 'b_asneeded']}
        default_warn_args = ['-Wall']
        self.warn_args = {'0': [],
                          '1': default_warn_args,
                          '2': default_warn_args + ['-Wextra'],
                          '3': default_warn_args + ['-Wextra', '-Wpedantic']}

    # FIXME: use _build_wrapper to call this so that linker flags from the env
    # get applied
    def get_library_dirs(self, env: 'Environment', elf_class: T.Optional[int] = None) -> T.List[str]:
        os_env = os.environ.copy()
        os_env['LC_ALL'] = 'C'
        stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1]
        for line in stdo.split('\n'):
            if line.startswith('libraries:'):
                # lcc does not include '=' in --print-search-dirs output. Also it could show nonexistent dirs.
                libstr = line.split(' ', 1)[1]
                return [os.path.realpath(p) for p in libstr.split(':') if os.path.exists(p)]
        return []

    def get_program_dirs(self, env: 'Environment') -> T.List[str]:
        os_env = os.environ.copy()
        os_env['LC_ALL'] = 'C'
        stdo = Popen_safe(self.exelist + ['--print-search-dirs'], env=os_env)[1]
        for line in stdo.split('\n'):
            if line.startswith('programs:'):
                # lcc does not include '=' in --print-search-dirs output.
                libstr = line.split(' ', 1)[1]
                return [os.path.realpath(p) for p in libstr.split(':')]
        return []

    def get_default_include_dirs(self) -> T.List[str]:
        os_env = os.environ.copy()
        os_env['LC_ALL'] = 'C'
        p = subprocess.Popen(self.exelist + ['-xc', '-E', '-v', '-'], env=os_env, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stderr = p.stderr.read().decode('utf-8', errors='replace')
        includes = []
        for line in stderr.split('\n'):
            if line.lstrip().startswith('--sys_include'):
                includes.append(re.sub(r'\s*\\$', '', re.sub(r'^\s*--sys_include\s*', '', line)))
        return includes

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

    def get_prelink_args(self, prelink_name: str, obj_list: T.List[str]) -> T.List[str]:
        return ['-r', '-nodefaultlibs', '-nostartfiles', '-o', prelink_name] + obj_list

    def get_pch_suffix(self) -> str:
        # Actually it's not supported for now, but probably will be supported in future
        return 'pch'

    def get_option_compile_args(self, options: 'KeyedOptionDictType') -> T.List[str]:
        args = []
        std = options[OptionKey('std', lang=self.language, machine=self.for_machine)]
        if std.value != 'none':
            args.append('-std=' + std.value)
        return args

    def openmp_flags(self) -> T.List[str]:
        return ['-fopenmp']
