# SPDX-License-Identifier: Apache-2.0
# Copyright 2022 Mark Bolhuis <mark@bolhuis.dev>

from __future__ import annotations
import os
import typing as T

from . import ExtensionModule, ModuleReturnValue, ModuleInfo
from ..build import CustomTarget
from ..interpreter.type_checking import NoneType, in_set_validator
from ..interpreterbase import typed_pos_args, typed_kwargs, KwargInfo, FeatureNew
from ..mesonlib import File, MesonException

if T.TYPE_CHECKING:
    from typing_extensions import Literal, TypedDict

    from . import ModuleState
    from ..build import Executable
    from ..dependencies import Dependency
    from ..interpreter import Interpreter
    from ..programs import ExternalProgram
    from ..mesonlib import FileOrString

    class ScanXML(TypedDict):

        public: bool
        client: bool
        server: bool
        include_core_only: bool

    class FindProtocol(TypedDict):

        state: Literal['stable', 'staging', 'unstable']
        version: T.Optional[int]

class WaylandModule(ExtensionModule):

    INFO = ModuleInfo('wayland', '0.62.0', stabilized='1.8.0')

    def __init__(self, interpreter: Interpreter) -> None:
        super().__init__(interpreter)

        self.protocols_dep: T.Optional[Dependency] = None
        self.pkgdatadir: T.Optional[str] = None
        self.scanner_bin: T.Optional[T.Union[ExternalProgram, Executable]] = None

        self.methods.update({
            'scan_xml': self.scan_xml,
            'find_protocol': self.find_protocol,
        })

    @typed_pos_args('wayland.scan_xml', varargs=(str, File), min_varargs=1)
    @typed_kwargs(
        'wayland.scan_xml',
        KwargInfo('public', bool, default=False),
        KwargInfo('client', bool, default=True),
        KwargInfo('server', bool, default=False),
        KwargInfo('include_core_only', bool, default=True, since='0.64.0'),
    )
    def scan_xml(self, state: ModuleState, args: T.Tuple[T.List[FileOrString]], kwargs: ScanXML) -> ModuleReturnValue:
        if self.scanner_bin is None:
            # wayland-scanner from BUILD machine must have same version as wayland
            # libraries from HOST machine.
            dep = state.dependency('wayland-client')
            self.scanner_bin = state.find_tool('wayland-scanner', 'wayland-scanner', 'wayland_scanner',
                                               wanted=dep.version)

        scope = 'public' if kwargs['public'] else 'private'
        # We have to cast because mypy can't deduce these are literals
        sides = [i for i in T.cast("T.List[Literal['client', 'server']]", ['client', 'server']) if kwargs[i]]
        if not sides:
            raise MesonException('At least one of client or server keyword argument must be set to true.')

        xml_files = self.interpreter.source_strings_to_files(args[0])
        targets: T.List[CustomTarget] = []
        for xml_file in xml_files:
            name = os.path.splitext(os.path.basename(xml_file.fname))[0]

            code = CustomTarget(
                f'{name}-protocol',
                state.subdir,
                state.subproject,
                state.environment,
                [self.scanner_bin, f'{scope}-code', '@INPUT@', '@OUTPUT@'],
                [xml_file],
                [f'{name}-protocol.c'],
                backend=state.backend,
            )
            targets.append(code)

            for side in sides:
                command = [self.scanner_bin, f'{side}-header', '@INPUT@', '@OUTPUT@']
                if kwargs['include_core_only']:
                    command.append('--include-core-only')

                header = CustomTarget(
                    f'{name}-{side}-protocol',
                    state.subdir,
                    state.subproject,
                    state.environment,
                    command,
                    [xml_file],
                    [f'{name}-{side}-protocol.h'],
                    backend=state.backend,
                )
                targets.append(header)

        return ModuleReturnValue(targets, targets)

    @typed_pos_args('wayland.find_protocol', str)
    @typed_kwargs(
        'wayland.find_protocol',
        KwargInfo('state', str, default='stable', validator=in_set_validator({'stable', 'staging', 'unstable'})),
        KwargInfo('version', (int, NoneType)),
    )
    def find_protocol(self, state: ModuleState, args: T.Tuple[str], kwargs: FindProtocol) -> File:
        base_name = args[0]
        xml_state = kwargs['state']
        version = kwargs['version']

        if xml_state != 'stable' and version is None:
            raise MesonException(f'{xml_state} protocols require a version number.')

        if xml_state == 'stable' and version is not None:
            FeatureNew.single_use('Version number in stable wayland protocol', '1.5.0', state.subproject, location=state.current_node)

        if self.protocols_dep is None:
            self.protocols_dep = state.dependency('wayland-protocols')

        if self.pkgdatadir is None:
            self.pkgdatadir = self.protocols_dep.get_variable(pkgconfig='pkgdatadir', internal='pkgdatadir')

        xml_name = base_name
        if xml_state == 'unstable':
            xml_name += '-unstable'
        if version is not None:
            xml_name += f'-v{version}'
        xml_name += '.xml'

        path = os.path.join(self.pkgdatadir, xml_state, base_name, xml_name)

        if not os.path.exists(path):
            raise MesonException(f'The file {path} does not exist.')

        return File.from_absolute_file(path)


def initialize(interpreter: Interpreter) -> WaylandModule:
    return WaylandModule(interpreter)
