# Copyright 2022 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.
"""pw_ide test classes."""

from contextlib import contextmanager
from io import TextIOWrapper
from pathlib import Path
import tempfile
from typing import Generator, List, Optional, Tuple, Union
import unittest

from pw_ide.settings import IdeSettings


class TempDirTestCase(unittest.TestCase):
    """Run tests that need access to a temporary directory."""
    def setUp(self) -> None:
        self.temp_dir = tempfile.TemporaryDirectory()
        self.temp_dir_path = Path(self.temp_dir.name)

    def tearDown(self) -> None:
        self.temp_dir.cleanup()
        return super().tearDown()

    @contextmanager
    def make_temp_file(
        self,
        filename: Union[Path, str],
        content: str = ''
    ) -> Generator[Tuple[TextIOWrapper, Path], None, None]:
        """Create a temp file in the test case's temp dir.

        Returns a tuple containing the file reference and the file's path.
        The file can be read immediately.
        """
        path = self.temp_dir_path / filename

        with open(path, 'a+', encoding='utf-8') as file:
            file.write(content)
            file.flush()
            file.seek(0)
            yield (file, path)

    @contextmanager
    def open_temp_file(
        self,
        filename: Union[Path, str],
    ) -> Generator[Tuple[TextIOWrapper, Path], None, None]:
        """Open an existing temp file in the test case's temp dir.

        Returns a tuple containing the file reference and the file's path.
        """
        path = self.temp_dir_path / filename

        with open(path, 'r', encoding='utf-8') as file:
            yield (file, path)

    @contextmanager
    def make_temp_files(
        self, files_data: List[Tuple[Union[Path, str], str]]
    ) -> Generator[List[TextIOWrapper], None, None]:
        """Create several temp files in the test case's temp dir.

        Provide a list of file name and content tuples. Saves you the trouble
        of excessive `with self.make_temp_file, self.make_temp_file...`
        nesting, and allows programmatic definition of multiple temp file
        contexts. Files can be read immediately.
        """
        files: List[TextIOWrapper] = []

        for filename, content in files_data:
            file = open(self.path_in_temp_dir(filename),
                        'a+',
                        encoding='utf-8')
            file.write(content)
            file.flush()
            file.seek(0)
            files.append(file)

        yield files

        for file in files:
            file.close()

    @contextmanager
    def open_temp_files(
        self, files_data: List[Union[Path, str]]
    ) -> Generator[List[TextIOWrapper], None, None]:
        """Open several existing temp files in the test case's temp dir.

        Provide a list of file names. Saves you the trouble of excessive
        `with self.open_temp_file, self.open_temp_file...` nesting, and allows
        programmatic definition of multiple temp file contexts.
        """
        files: List[TextIOWrapper] = []

        for filename in files_data:
            file = open(self.path_in_temp_dir(filename), 'r', encoding='utf-8')
            files.append(file)

        yield files

        for file in files:
            file.close()

    def path_in_temp_dir(self, path: Union[Path, str]) -> Path:
        """Place a path into the test case's temp dir.

        This only works with a relative path; with an absolute path, this is a
        no-op.
        """
        return self.temp_dir_path / path

    def paths_in_temp_dir(self, *paths: Union[Path, str]) -> List[Path]:
        """Place several paths into the test case's temp dir.

        This only works with relative paths; with absolute paths, this is a
        no-op.
        """
        return [self.path_in_temp_dir(path) for path in paths]


class PwIdeTestCase(TempDirTestCase):
    """A test case for testing `pw_ide`.

    Provides a temp dir for testing file system actions and access to IDE
    settings that wrap the temp dir.
    """
    def make_ide_settings(self,
                          working_dir: Optional[Union[str, Path]] = None,
                          targets: Optional[List[str]] = None) -> IdeSettings:
        """Make settings that wrap provided paths in the temp path."""

        if working_dir is not None:
            working_dir_path = self.path_in_temp_dir(working_dir)
        else:
            working_dir_path = self.temp_dir_path

        if targets is None:
            targets = []

        return IdeSettings(False,
                           False,
                           False,
                           default_config={
                               'working_dir': str(working_dir_path),
                               'targets': targets,
                           })
