#!/usr/bin/env python3

# Copyright (c) 2022 Project CHIP Authors
#
# 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.

import os
import unittest
import yaml
import logging
from typing import List
from dataclasses import dataclass, field

try:
    from idl.matter_idl_parser import CreateParser
except:
    import sys

    sys.path.append(os.path.abspath(
        os.path.join(os.path.dirname(__file__), '..')))
    from idl.matter_idl_parser import CreateParser

from idl.matter_idl_types import Idl
from idl.generators.java import JavaGenerator
from idl.generators.bridge import BridgeGenerator
from idl.generators.cpp.application import CppApplicationGenerator
from idl.generators import GeneratorStorage


TESTS_DIR = os.path.join(os.path.dirname(__file__), "tests")
REGENERATE_GOLDEN_IMAGES = False


@dataclass
class ExpectedOutput:
    file_name: str
    golden_path: str


@dataclass
class GeneratorTestCase:
    input_idl: str
    outputs: List[ExpectedOutput] = field(default_factory=list)

    def add_outputs(self, yaml_outputs_dict):
        for file_name, golden_path in yaml_outputs_dict.items():
            self.outputs.append(ExpectedOutput(
                file_name=file_name, golden_path=golden_path))


class TestCaseStorage(GeneratorStorage):
    def __init__(self, test_case: GeneratorTestCase, checker: unittest.TestCase):
        super().__init__()
        self.test_case = test_case
        self.checker = checker
        self.checked_files = set()

    def get_existing_data_path(self, relative_path: str):
        for expected in self.test_case.outputs:
            if expected.file_name == relative_path:
                return os.path.join(TESTS_DIR, expected.golden_path)

        self.checker.fail("Expected output %s not found" % relative_path)
        return None

    def get_existing_data(self, relative_path: str):
        self.checked_files.add(relative_path)

        path = self.get_existing_data_path(relative_path)
        if path:
            with open(path, 'rt') as golden:
                return golden.read()

        # This will attempt a new write, causing a unit test failure
        self.checker.fail("Expected output %s not found" % relative_path)
        return None

    def write_new_data(self, relative_path: str, content: str):
        if REGENERATE_GOLDEN_IMAGES:
            print("RE-GENERATING %r" % relative_path)
            # Expect writing only on regeneration
            with open(self.get_existing_data_path(relative_path), 'wt') as golden:
                golden.write(content)
                return

        # This is a unit test failure: we do NOT expect
        # to write any new data

        # This will display actual diffs in the output files
        self.checker.assertEqual(
            self.get_existing_data(relative_path), content, "Content of %s" % relative_path)

        # Even if no diff, to be build system friendly, we do NOT expect any
        # actual data writes.
        raise AssertionError("Unexpected write to %s" % relative_path)


@dataclass
class GeneratorTest:
    generator_name: str
    test_cases: List[GeneratorTestCase] = field(default_factory=list)

    def add_test_cases(self, yaml_test_case_dict):
        for idl_path, outputs in yaml_test_case_dict.items():
            test_case = GeneratorTestCase(input_idl=idl_path)
            test_case.add_outputs(outputs)
            self.test_cases.append(test_case)

    def _create_generator(self, storage: GeneratorStorage, idl: Idl):
        if self.generator_name.lower() == 'java':
            return JavaGenerator(storage, idl)
        if self.generator_name.lower() == 'bridge':
            return BridgeGenerator(storage, idl)
        if self.generator_name.lower() == 'cpp-app':
            return CppApplicationGenerator(storage, idl)
        else:
            raise Exception("Unknown generator for testing: %s",
                            self.generator_name.lower())

    def run_test_cases(self, checker: unittest.TestCase):
        for test in self.test_cases:
            with checker.subTest(idl=test.input_idl):
                storage = TestCaseStorage(test, checker)
                with open(os.path.join(TESTS_DIR, test.input_idl), 'rt') as stream:
                    idl = CreateParser().parse(stream.read())

                generator = self._create_generator(storage, idl)
                generator.render(dry_run=False)

                checker.assertEqual(storage.checked_files, set(
                    map(lambda x: x.file_name, test.outputs)))


def build_tests(yaml_data) -> List[GeneratorTest]:
    """
    Transforms the YAML dictonary (Dict[str, Dict[str, Dict[str,str]]]) into
    a generator test structure.
    """
    result = []

    for key, test_cases in yaml_data.items():
        generator = GeneratorTest(generator_name=key)
        generator.add_test_cases(test_cases)
        result.append(generator)

    return result


class TestGenerators(unittest.TestCase):
    def test_generators(self):
        with open(os.path.join(TESTS_DIR, "available_tests.yaml"), 'rt') as stream:
            yaml_data = yaml.safe_load(stream)

        for test in build_tests(yaml_data):
            with self.subTest(generator=test.generator_name):
                test.run_test_cases(self)


if __name__ == '__main__':
    if 'IDL_GOLDEN_REGENERATE' in os.environ:
        # run with `IDL_GOLDEN_REGENERATE=1` to cause a regeneration of test
        # data. Then one can use `git diff` to see if the deltas make sense
        REGENERATE_GOLDEN_IMAGES = True
    unittest.main()
