# Copyright 2021 The Pigweed 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
#
#     https://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.
"""Tests for pw_build.create_python_tree"""

import io
import os
from pathlib import Path
import tempfile
from typing import List
import unittest

from parameterized import parameterized  # type: ignore

from pw_build.python_package import PythonPackage
from pw_build.create_python_tree import (
    build_python_tree,
    copy_extra_files,
    load_common_config,
    update_config_with_packages,
)
from pw_build.generate_python_package import _PYPROJECT_FILE as PYPROJECT_TEXT


def _setup_cfg(package_name: str, install_requires: str = '') -> str:
    return f'''
[metadata]
name = {package_name}
version = 0.0.1
author = Pigweed Authors
author_email = pigweed-developers@googlegroups.com
description = Pigweed swiss-army knife

[options]
packages = find:
zip_safe = False
{install_requires}

[options.package_data]
{package_name} =
    py.typed
    '''


def _create_fake_python_package(location: Path,
                                package_name: str,
                                files: List[str],
                                install_requires: str = '') -> None:
    for file in files:
        destination = location / file
        destination.parent.mkdir(parents=True, exist_ok=True)
        text = f'"""{package_name}"""'
        if str(destination).endswith('setup.cfg'):
            text = _setup_cfg(package_name, install_requires)
        elif str(destination).endswith('pyproject.toml'):
            # Make sure pyproject.toml file has valid syntax.
            text = PYPROJECT_TEXT
        destination.write_text(text)


class TestCreatePythonTree(unittest.TestCase):
    """Integration tests for create_python_tree."""
    def setUp(self):
        self.maxDiff = None  # pylint: disable=invalid-name
        # Save the starting working directory for returning to later.
        self.start_dir = Path.cwd()
        # Create a temp out directory
        self.temp_dir = tempfile.TemporaryDirectory()

    def tearDown(self):
        # cd to the starting dir before cleaning up the temp out directory
        os.chdir(self.start_dir)
        # Delete the TemporaryDirectory
        self.temp_dir.cleanup()

    def _check_result_paths_equal(self, install_dir, expected_results) -> None:
        # Normalize path strings to posix before comparing.
        expected_paths = set(Path(p).as_posix() for p in expected_results)
        actual_paths = set(
            p.relative_to(install_dir).as_posix()
            for p in install_dir.glob('**/*') if p.is_file())
        self.assertEqual(expected_paths, actual_paths)

    def test_update_config_with_packages(self) -> None:
        """Test merging package setup.cfg files."""
        temp_root = Path(self.temp_dir.name)
        common_config = temp_root / 'common_setup.cfg'
        common_config.write_text('''
[metadata]
name = megapackage
version = 0.0.1
author = Pigweed Authors
author_email = pigweed-developers@googlegroups.com
description = Pigweed swiss-army knife

[options]
zip_safe = False
''')
        config = load_common_config(common_config=common_config,
                                    append_git_sha=False,
                                    append_date=False)
        config_metadata = dict(config['metadata'].items())
        self.assertIn('name', config_metadata)

        pkg1_root = temp_root / 'pkg1'
        pkg2_root = temp_root / 'pkg2'
        _create_fake_python_package(pkg1_root,
                                    'mars', [
                                        'planets/BUILD.mars_rocket',
                                        'planets/mars/__init__.py',
                                        'planets/mars/__main__.py',
                                        'planets/mars/moons/__init__.py',
                                        'planets/mars/moons/deimos.py',
                                        'planets/mars/moons/phobos.py',
                                        'planets/hohmann_transfer_test.py',
                                        'planets/pyproject.toml',
                                        'planets/setup.cfg',
                                    ],
                                    install_requires='''
install_requires =
        coloredlogs
        coverage
        cryptography
        graphlib-backport;python_version<'3.9'
        httpwatcher
''')

        os.chdir(pkg1_root)
        pkg1 = PythonPackage.from_dict(
            **{
                'generate_setup': {
                    'metadata': {
                        'name': 'mars',
                        'version': '0.0.1'
                    },
                },
                'inputs': [],
                'setup_sources': [
                    'planets/pyproject.toml',
                    'planets/setup.cfg',
                ],
                'sources': [
                    'planets/mars/__init__.py',
                    'planets/mars/__main__.py',
                    'planets/mars/moons/__init__.py',
                    'planets/mars/moons/deimos.py',
                    'planets/mars/moons/phobos.py',
                ],
                'tests': [
                    'planets/hohmann_transfer_test.py',
                ],
            })

        _create_fake_python_package(pkg2_root,
                                    'saturn', [
                                        'planets/BUILD.saturn_rocket',
                                        'planets/hohmann_transfer_test.py',
                                        'planets/pyproject.toml',
                                        'planets/saturn/__init__.py',
                                        'planets/saturn/__main__.py',
                                        'planets/saturn/misson.py',
                                        'planets/saturn/moons/__init__.py',
                                        'planets/saturn/moons/enceladus.py',
                                        'planets/saturn/moons/iapetus.py',
                                        'planets/saturn/moons/rhea.py',
                                        'planets/saturn/moons/titan.py',
                                        'planets/setup.cfg',
                                        'planets/setup.py',
                                    ],
                                    install_requires='''
install_requires =
        graphlib-backport;python_version<'3.9'
        httpwatcher
''')
        os.chdir(pkg2_root)
        pkg2 = PythonPackage.from_dict(
            **{
                'inputs': [],
                'setup_sources': [
                    'planets/pyproject.toml',
                    'planets/setup.cfg',
                    'planets/setup.py',
                ],
                'sources': [
                    'planets/saturn/__init__.py',
                    'planets/saturn/__main__.py',
                    'planets/saturn/misson.py',
                    'planets/saturn/moons/__init__.py',
                    'planets/saturn/moons/enceladus.py',
                    'planets/saturn/moons/iapetus.py',
                    'planets/saturn/moons/rhea.py',
                    'planets/saturn/moons/titan.py',
                ],
                'tests': [
                    'planets/hohmann_transfer_test.py',
                ]
            })

        update_config_with_packages(config=config,
                                    python_packages=[pkg1, pkg2])

        setup_cfg_text = io.StringIO()
        config.write(setup_cfg_text)
        expected_cfg = '''
[metadata]
name = megapackage
version = 0.0.1
author = Pigweed Authors
author_email = pigweed-developers@googlegroups.com
description = Pigweed swiss-army knife

[options]
zip_safe = False
packages = find:
install_requires =
    coloredlogs
    coverage
    cryptography
    graphlib-backport;python_version<'3.9'
    httpwatcher

[options.package_data]
mars =
    py.typed
saturn =
    py.typed

[options.entry_points]
'''
        result_cfg_lines = [
            line.rstrip().replace('\t', '    ')
            for line in setup_cfg_text.getvalue().splitlines() if line
        ]
        expected_cfg_lines = [
            line.rstrip() for line in expected_cfg.splitlines() if line
        ]
        self.assertEqual(result_cfg_lines, expected_cfg_lines)


    @parameterized.expand([
        (
            # Test name
            'working case',
            # Package name
            'mars',
            # File list
            [
                'planets/BUILD.mars_rocket',
                'planets/mars/__init__.py',
                'planets/mars/__main__.py',
                'planets/mars/moons/__init__.py',
                'planets/mars/moons/deimos.py',
                'planets/mars/moons/phobos.py',
                'planets/hohmann_transfer_test.py',
                'planets/pyproject.toml',
                'planets/setup.cfg',
            ],
            # Extra_files
            [],
            # Package definition
            {
                'generate_setup': {
                    'metadata': {
                        'name': 'mars',
                        'version': '0.0.1'
                    },
                },
                'inputs': [
                ],
                'setup_sources': [
                    'planets/pyproject.toml',
                    'planets/setup.cfg',
                ],
                'sources': [
                    'planets/mars/__init__.py',
                    'planets/mars/__main__.py',
                    'planets/mars/moons/__init__.py',
                    'planets/mars/moons/deimos.py',
                    'planets/mars/moons/phobos.py',
                ],
                'tests': [
                    'planets/hohmann_transfer_test.py',
                ],
            },
            # Output file list
            [
                'mars/__init__.py',
                'mars/__main__.py',
                'mars/moons/__init__.py',
                'mars/moons/deimos.py',
                'mars/moons/phobos.py',
                'mars/tests/hohmann_transfer_test.py',
            ],
        ),

        (
            # Test name
            'with extra files',
            # Package name
            'saturn',
            # File list
            [
                'planets/BUILD.saturn_rocket',
                'planets/hohmann_transfer_test.py',
                'planets/pyproject.toml',
                'planets/saturn/__init__.py',
                'planets/saturn/__main__.py',
                'planets/saturn/misson.py',
                'planets/saturn/moons/__init__.py',
                'planets/saturn/moons/enceladus.py',
                'planets/saturn/moons/iapetus.py',
                'planets/saturn/moons/rhea.py',
                'planets/saturn/moons/titan.py',
                'planets/setup.cfg',
                'planets/setup.py',
            ],
            # Extra files
            [
                'planets/BUILD.saturn_rocket > out/saturn/BUILD.rocket',
            ],
            # Package definition
            {
                'inputs': [
                ],
                'setup_sources': [
                    'planets/pyproject.toml',
                    'planets/setup.cfg',
                    'planets/setup.py',
                ],
                'sources': [
                    'planets/saturn/__init__.py',
                    'planets/saturn/__main__.py',
                    'planets/saturn/misson.py',
                    'planets/saturn/moons/__init__.py',
                    'planets/saturn/moons/enceladus.py',
                    'planets/saturn/moons/iapetus.py',
                    'planets/saturn/moons/rhea.py',
                    'planets/saturn/moons/titan.py',
                ],
                'tests': [
                    'planets/hohmann_transfer_test.py',
                ]
            },
            # Output file list
            [
                'saturn/BUILD.rocket',
                'saturn/__init__.py',
                'saturn/__main__.py',
                'saturn/misson.py',
                'saturn/moons/__init__.py',
                'saturn/moons/enceladus.py',
                'saturn/moons/iapetus.py',
                'saturn/moons/rhea.py',
                'saturn/moons/titan.py',
                'saturn/tests/hohmann_transfer_test.py',
            ],
        ),
    ]) # yapf: disable
    def test_build_python_tree(
        self,
        _test_name,
        package_name,
        file_list,
        extra_files,
        package_definition,
        expected_file_list,
    ) -> None:
        """Check results of build_python_tree and copy_extra_files."""
        temp_root = Path(self.temp_dir.name)
        _create_fake_python_package(temp_root, package_name, file_list)

        os.chdir(temp_root)
        install_dir = temp_root / 'out'

        package = PythonPackage.from_dict(**package_definition)
        build_python_tree(python_packages=[package],
                          tree_destination_dir=install_dir,
                          include_tests=True)
        copy_extra_files(extra_files)

        # Check expected files are in place.
        self._check_result_paths_equal(install_dir, expected_file_list)

    @parameterized.expand([
        (
            # Test name
            'everything in correct locations',
            # Package name
            'planets',
            # File list
            [
                'BUILD.mars_rocket',
            ],
            # Extra_files
            [
                'BUILD.mars_rocket > out/mars/BUILD.rocket',
            ],
            # Output file list
            [
                'mars/BUILD.rocket',
            ],
            # Should raise exception
            None,
        ),
        (
            # Test name
            'missing source files',
            # Package name
            'planets',
            # File list
            [
                'BUILD.mars_rocket',
            ],
            # Extra_files
            [
                'BUILD.venus_rocket > out/venus/BUILD.rocket',
            ],
            # Output file list
            [],
            # Should raise exception
            FileNotFoundError,
        ),
        (
            # Test name
            'existing destination files',
            # Package name
            'planets',
            # File list
            [
                'BUILD.jupiter_rocket',
                'out/jupiter/BUILD.rocket',
            ],
            # Extra_files
            [
                'BUILD.jupiter_rocket > out/jupiter/BUILD.rocket',
            ],
            # Output file list
            [],
            # Should raise exception
            FileExistsError,
        ),
    ]) # yapf: disable
    def test_copy_extra_files(
        self,
        _test_name,
        package_name,
        file_list,
        extra_files,
        expected_file_list,
        should_raise_exception,
    ) -> None:
        """Check results of build_python_tree and copy_extra_files."""
        temp_root = Path(self.temp_dir.name)
        _create_fake_python_package(temp_root, package_name, file_list)

        os.chdir(temp_root)
        install_dir = temp_root / 'out'

        # If exceptions should be raised
        if should_raise_exception:
            with self.assertRaises(should_raise_exception):
                copy_extra_files(extra_files)
            return

        # Do the copy
        copy_extra_files(extra_files)
        # Check expected files are in place.
        self._check_result_paths_equal(install_dir, expected_file_list)


if __name__ == '__main__':
    unittest.main()
