# SPDX-License-Identifier: Apache-2.0
# Copyright 2013-2024 Contributors to the The Meson project
# Copyright © 2024 Intel Corporation

from __future__ import annotations
import typing as T
import configparser
import os

from . import mparser

from .mesonlib import MesonException

if T.TYPE_CHECKING:
    from typing_extensions import TypeAlias

    from .coredata import StrOrBytesPath

    SectionT: TypeAlias = T.Union[str, int, bool, T.List[str], T.List['SectionT']]


class CmdLineFileParser(configparser.ConfigParser):
    def __init__(self) -> None:
        # We don't want ':' as key delimiter, otherwise it would break when
        # storing subproject options like "subproject:option=value"
        super().__init__(delimiters=['='], interpolation=None)

    def read(self, filenames: T.Union['StrOrBytesPath', T.Iterable['StrOrBytesPath']], encoding: T.Optional[str] = 'utf-8') -> T.List[str]:
        return super().read(filenames, encoding)

    def optionxform(self, optionstr: str) -> str:
        # Don't call str.lower() on keys
        return optionstr


class MachineFileParser():
    def __init__(self, filenames: T.List[str], sourcedir: str) -> None:
        self.parser = CmdLineFileParser()
        self.constants: T.Dict[str, SectionT] = {'True': True, 'False': False}
        self.sections: T.Dict[str, T.Dict[str, SectionT]] = {}

        for fname in filenames:
            try:
                with open(fname, encoding='utf-8') as f:
                    content = f.read()
            except UnicodeDecodeError as e:
                raise MesonException(f'Malformed machine file {fname!r} failed to parse as unicode: {e}')

            content = content.replace('@GLOBAL_SOURCE_ROOT@', sourcedir)
            content = content.replace('@DIRNAME@', os.path.dirname(fname))
            try:
                self.parser.read_string(content, fname)
            except configparser.Error as e:
                raise MesonException(f'Malformed machine file: {e}')

        # Parse [constants] first so they can be used in other sections
        if self.parser.has_section('constants'):
            self.constants.update(self._parse_section('constants'))

        for s in self.parser.sections():
            if s == 'constants':
                continue
            self.sections[s] = self._parse_section(s)

    def _parse_section(self, s: str) -> T.Dict[str, SectionT]:
        self.scope = self.constants.copy()
        section: T.Dict[str, SectionT] = {}
        for entry, value in self.parser.items(s):
            if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry:
                raise MesonException(f'Malformed variable name {entry!r} in machine file.')
            # Windows paths...
            value = value.replace('\\', '\\\\')
            try:
                ast = mparser.Parser(value, 'machinefile').parse()
                if not ast.lines:
                    raise MesonException('value cannot be empty')
                res = self._evaluate_statement(ast.lines[0])
            except MesonException as e:
                raise MesonException(f'Malformed value in machine file variable {entry!r}: {str(e)}.')
            except KeyError as e:
                raise MesonException(f'Undefined constant {e.args[0]!r} in machine file variable {entry!r}.')
            section[entry] = res
            self.scope[entry] = res
        return section

    def _evaluate_statement(self, node: mparser.BaseNode) -> SectionT:
        if isinstance(node, (mparser.StringNode)):
            return node.value
        elif isinstance(node, mparser.BooleanNode):
            return node.value
        elif isinstance(node, mparser.NumberNode):
            return node.value
        elif isinstance(node, mparser.ParenthesizedNode):
            return self._evaluate_statement(node.inner)
        elif isinstance(node, mparser.ArrayNode):
            return [self._evaluate_statement(arg) for arg in node.args.arguments]
        elif isinstance(node, mparser.IdNode):
            return self.scope[node.value]
        elif isinstance(node, mparser.ArithmeticNode):
            l = self._evaluate_statement(node.left)
            r = self._evaluate_statement(node.right)
            if node.operation == 'add':
                if isinstance(l, str) and isinstance(r, str):
                    return l + r
                if isinstance(l, list) and isinstance(r, list):
                    return l + r
            elif node.operation == 'div':
                if isinstance(l, str) and isinstance(r, str):
                    return os.path.join(l, r)
        raise MesonException('Unsupported node type')

def parse_machine_files(filenames: T.List[str], sourcedir: str) -> T.Dict[str, T.Dict[str, SectionT]]:
    parser = MachineFileParser(filenames, sourcedir)
    return parser.sections


class MachineFileStore:
    def __init__(self, native_files: T.Optional[T.List[str]], cross_files: T.Optional[T.List[str]], source_dir: str):
        self.native = parse_machine_files(native_files if native_files is not None else [], source_dir)
        self.cross = parse_machine_files(cross_files if cross_files is not None else [], source_dir)
