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

from __future__ import annotations
import itertools
import typing as T

from . import ExtensionModule, ModuleReturnValue, ModuleInfo
from .. import build
from .. import mesonlib
from ..interpreter.type_checking import CT_INPUT_KW
from ..interpreterbase.decorators import KwargInfo, typed_kwargs, typed_pos_args

if T.TYPE_CHECKING:
    from typing_extensions import TypedDict

    from . import ModuleState
    from ..interpreter import Interpreter
    from ..programs import ExternalProgram

    class ProjectKwargs(TypedDict):

        sources: T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]]
        constraint_file: T.Union[mesonlib.FileOrString, build.GeneratedTypes]

class IceStormModule(ExtensionModule):

    INFO = ModuleInfo('FPGA/Icestorm', '0.45.0', unstable=True)

    def __init__(self, interpreter: Interpreter) -> None:
        super().__init__(interpreter)
        self.tools: T.Dict[str, ExternalProgram] = {}
        self.methods.update({
            'project': self.project,
        })

    def detect_tools(self, state: ModuleState) -> None:
        self.tools['yosys'] = state.find_program('yosys')
        self.tools['arachne'] = state.find_program('arachne-pnr')
        self.tools['icepack'] = state.find_program('icepack')
        self.tools['iceprog'] = state.find_program('iceprog')
        self.tools['icetime'] = state.find_program('icetime')

    @typed_pos_args('icestorm.project', str,
                    varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex,
                             build.GeneratedList))
    @typed_kwargs(
        'icestorm.project',
        CT_INPUT_KW.evolve(name='sources'),
        KwargInfo(
            'constraint_file',
            (str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList),
            required=True,
        )
    )
    def project(self, state: ModuleState,
                args: T.Tuple[str, T.List[T.Union[mesonlib.FileOrString, build.GeneratedTypes]]],
                kwargs: ProjectKwargs) -> ModuleReturnValue:
        if not self.tools:
            self.detect_tools(state)
        proj_name, arg_sources = args
        all_sources = self.interpreter.source_strings_to_files(
            list(itertools.chain(arg_sources, kwargs['sources'])))

        blif_target = build.CustomTarget(
            f'{proj_name}_blif',
            state.subdir,
            state.subproject,
            state.environment,
            [self.tools['yosys'], '-q', '-p', 'synth_ice40 -blif @OUTPUT@', '@INPUT@'],
            all_sources,
            [f'{proj_name}.blif'],
        )

        asc_target = build.CustomTarget(
            f'{proj_name}_asc',
            state.subdir,
            state.subproject,
            state.environment,
            [self.tools['arachne'], '-q', '-d', '1k', '-p', '@INPUT@', '-o', '@OUTPUT@'],
            [kwargs['constraint_file'], blif_target],
            [f'{proj_name}.asc'],
        )

        bin_target = build.CustomTarget(
            f'{proj_name}_bin',
            state.subdir,
            state.subproject,
            state.environment,
            [self.tools['icepack'], '@INPUT@', '@OUTPUT@'],
            [asc_target],
            [f'{proj_name}.bin'],
            build_by_default=True,
        )

        upload_target = build.RunTarget(
            f'{proj_name}-upload',
            [self.tools['iceprog'], bin_target],
            [],
            state.subdir,
            state.subproject,
            state.environment,
        )

        time_target = build.RunTarget(
            f'{proj_name}-time',
            [self.tools['icetime'], bin_target],
            [],
            state.subdir,
            state.subproject,
            state.environment,
        )

        return ModuleReturnValue(
            None,
            [blif_target, asc_target, bin_target, upload_target, time_target])


def initialize(interp: Interpreter) -> IceStormModule:
    return IceStormModule(interp)
