# Copyright 2022 Mark Bolhuis <mark@bolhuis.dev>

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

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
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', unstable=True)

    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:
            raise MesonException('stable protocols do not require a version number.')

        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')

        if xml_state == 'stable':
            xml_name = f'{base_name}.xml'
        elif xml_state == 'staging':
            xml_name = f'{base_name}-v{version}.xml'
        else:
            xml_name = f'{base_name}-unstable-v{version}.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)
