# 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_cli.plugins."""

from pathlib import Path
import sys
import tempfile
import types
from typing import Dict, Iterator
import unittest

from pw_cli import plugins


def _no_docstring() -> int:
    return 123


def _with_docstring() -> int:
    """This docstring is brought to you courtesy of Pigweed."""
    return 456


def _create_files(directory: str, files: Dict[str, str]) -> Iterator[Path]:
    for relative_path, contents in files.items():
        path = Path(directory) / relative_path
        path.parent.mkdir(exist_ok=True, parents=True)
        path.write_text(contents)
        yield path


class TestPlugin(unittest.TestCase):
    """Tests for plugins.Plugins."""
    def test_target_name_attribute(self) -> None:
        self.assertEqual(
            plugins.Plugin('abc', _no_docstring).target_name,
            f'{__name__}._no_docstring')

    def test_target_name_no_name_attribute(self) -> None:
        has_no_name = 'no __name__'
        self.assertFalse(hasattr(has_no_name, '__name__'))

        self.assertEqual(
            plugins.Plugin('abc', has_no_name).target_name,
            '<unknown>.no __name__')


_TEST_PLUGINS = {
    'TEST_PLUGINS': (f'test_plugin {__name__} _with_docstring\n'
                     f'other_plugin {__name__} _no_docstring\n'),
    'nested/in/dirs/TEST_PLUGINS':
    f'test_plugin {__name__} _no_docstring\n',
}


class TestPluginRegistry(unittest.TestCase):
    """Tests for plugins.Registry."""
    def setUp(self) -> None:
        self._registry = plugins.Registry(
            validator=plugins.callable_with_no_args)

    def test_register(self) -> None:
        self.assertIsNotNone(self._registry.register('a_plugin',
                                                     _no_docstring))
        self.assertIs(self._registry['a_plugin'].target, _no_docstring)

    def test_register_by_name(self) -> None:
        self.assertIsNotNone(
            self._registry.register_by_name('plugin_one', __name__,
                                            '_no_docstring'))
        self.assertIsNotNone(
            self._registry.register('plugin_two', _no_docstring))

        self.assertIs(self._registry['plugin_one'].target, _no_docstring)
        self.assertIs(self._registry['plugin_two'].target, _no_docstring)

    def test_register_by_name_undefined_module(self) -> None:
        with self.assertRaisesRegex(plugins.Error, 'No module named'):
            self._registry.register_by_name('plugin_two', 'not a module',
                                            'something')

    def test_register_by_name_undefined_function(self) -> None:
        with self.assertRaisesRegex(plugins.Error, 'does not exist'):
            self._registry.register_by_name('plugin_two', __name__, 'nothing')

    def test_register_fails_validation(self) -> None:
        with self.assertRaisesRegex(plugins.Error, 'must be callable'):
            self._registry.register('plugin_two', 'not function')

    def test_run_with_argv_sets_sys_argv(self) -> None:
        def stash_argv() -> int:
            self.assertEqual(['pw go', '1', '2'], sys.argv)
            return 1

        self.assertIsNotNone(self._registry.register('go', stash_argv))

        original_argv = sys.argv
        self.assertEqual(self._registry.run_with_argv('go', ['1', '2']), 1)
        self.assertIs(sys.argv, original_argv)

    def test_run_with_argv_registered_plugin(self) -> None:
        with self.assertRaises(KeyError):
            self._registry.run_with_argv('plugin_one', [])

    def test_register_cannot_overwrite(self) -> None:
        self.assertIsNotNone(self._registry.register('foo', lambda: None))
        self.assertIsNotNone(
            self._registry.register_by_name('bar', __name__, '_no_docstring'))

        with self.assertRaises(plugins.Error):
            self._registry.register('foo', lambda: None)

        with self.assertRaises(plugins.Error):
            self._registry.register('bar', lambda: None)

    def test_register_directory_innermost_takes_priority(self) -> None:
        with tempfile.TemporaryDirectory() as tempdir:
            paths = list(_create_files(tempdir, _TEST_PLUGINS))
            self._registry.register_directory(paths[1].parent, 'TEST_PLUGINS')

        self.assertEqual(self._registry.run_with_argv('test_plugin', []), 123)

    def test_register_directory_only_searches_up(self) -> None:
        with tempfile.TemporaryDirectory() as tempdir:
            paths = list(_create_files(tempdir, _TEST_PLUGINS))
            self._registry.register_directory(paths[0].parent, 'TEST_PLUGINS')

        self.assertEqual(self._registry.run_with_argv('test_plugin', []), 456)

    def test_register_directory_with_restriction(self) -> None:
        with tempfile.TemporaryDirectory() as tempdir:
            paths = list(_create_files(tempdir, _TEST_PLUGINS))
            self._registry.register_directory(paths[0].parent, 'TEST_PLUGINS',
                                              Path(tempdir, 'nested', 'in'))

        self.assertNotIn('other_plugin', self._registry)

    def test_register_same_file_multiple_times_no_error(self) -> None:
        with tempfile.TemporaryDirectory() as tempdir:
            paths = list(_create_files(tempdir, _TEST_PLUGINS))
            self._registry.register_file(paths[0])
            self._registry.register_file(paths[0])
            self._registry.register_file(paths[0])

        self.assertIs(self._registry['test_plugin'].target, _with_docstring)

    def test_help_uses_function_or_module_docstring(self) -> None:
        self.assertIsNotNone(self._registry.register('a', _no_docstring))
        self.assertIsNotNone(self._registry.register('b', _with_docstring))

        self.assertIn(__doc__, '\n'.join(self._registry.detailed_help(['a'])))

        self.assertNotIn(__doc__,
                         '\n'.join(self._registry.detailed_help(['b'])))
        self.assertIn(_with_docstring.__doc__,
                      '\n'.join(self._registry.detailed_help(['b'])))

    def test_empty_string_if_no_help(self) -> None:
        fake_module_name = f'{__name__}.fake_module_for_test{id(self)}'
        fake_module = types.ModuleType(fake_module_name)
        self.assertIsNone(fake_module.__doc__)

        sys.modules[fake_module_name] = fake_module

        try:

            function = lambda: None
            function.__module__ = fake_module_name
            self.assertIsNotNone(self._registry.register('a', function))

            self.assertEqual(self._registry['a'].help(full=False), '')
            self.assertEqual(self._registry['a'].help(full=True), '')
        finally:
            del sys.modules[fake_module_name]

    def test_decorator_not_called(self) -> None:
        @self._registry.plugin
        def nifty() -> None:
            pass

        self.assertEqual(self._registry['nifty'].target, nifty)

    def test_decorator_called_no_args(self) -> None:
        @self._registry.plugin()
        def nifty() -> None:
            pass

        self.assertEqual(self._registry['nifty'].target, nifty)

    def test_decorator_called_with_args(self) -> None:
        @self._registry.plugin(name='nifty')
        def my_nifty_keen_plugin() -> None:
            pass

        self.assertEqual(self._registry['nifty'].target, my_nifty_keen_plugin)


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