# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
#
# Copyright (C) 2017-2018 Canonical Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import logging

import fixtures
from testtools.matchers import Contains, Equals

from snapcraft import extractors
from snapcraft.internal import errors
from snapcraft.internal.pluginhandler import extract_metadata
from tests import fixture_setup, unit


class MetadataExtractionTestCase(unit.TestCase):
    def test_handled_file(self):
        open("test-metadata-file", "w").close()

        def _fake_extractor(file_path, workdir):
            return extractors.ExtractedMetadata(
                summary="test summary", description="test description"
            )

        self.useFixture(fixture_setup.FakeMetadataExtractor("fake", _fake_extractor))

        metadata = extract_metadata("test-part", "test-metadata-file", workdir=".")
        self.assertThat(metadata.get_summary(), Equals("test summary"))
        self.assertThat(metadata.get_description(), Equals("test description"))

    def test_unhandled_file(self):
        open("unhandled-file", "w").close()

        def _fake_extractor(file_path, workdir):
            raise extractors.UnhandledFileError(file_path, "fake")

        self.useFixture(fixture_setup.FakeMetadataExtractor("fake", _fake_extractor))

        raised = self.assertRaises(
            errors.UnhandledMetadataFileTypeError,
            extract_metadata,
            "test-part",
            "unhandled-file",
            workdir=".",
        )

        self.assertThat(raised.path, Equals("unhandled-file"))

    def test_extractor_missing_extract_function(self):
        fake_logger = fixtures.FakeLogger(level=logging.WARN)
        self.useFixture(fake_logger)

        open("unhandled-file", "w").close()

        def _fake_extractor(file_path, workdir):
            raise extractors.UnhandledFileError(file_path, "fake")

        self.useFixture(
            fixture_setup.FakeMetadataExtractor("fake", _fake_extractor, "not_extract")
        )

        raised = self.assertRaises(
            errors.UnhandledMetadataFileTypeError,
            extract_metadata,
            "test-part",
            "unhandled-file",
            workdir=".",
        )

        self.assertThat(raised.path, Equals("unhandled-file"))
        self.assertThat(
            fake_logger.output,
            Contains("'fake' doesn't include the 'extract' function"),
        )

    def test_extractor_returning_invalid_things(self):
        open("unhandled-file", "w").close()

        def _fake_extractor(file_path, workdir):
            return "I'm not metadata!"

        self.useFixture(fixture_setup.FakeMetadataExtractor("fake", _fake_extractor))

        raised = self.assertRaises(
            errors.InvalidExtractorValueError,
            extract_metadata,
            "test-part",
            "unhandled-file",
            workdir=".",
        )

        self.assertThat(raised.path, Equals("unhandled-file"))
        self.assertThat(raised.extractor_name, Equals("fake"))

    def test_missing_file(self):
        raised = self.assertRaises(
            errors.MissingMetadataFileError,
            extract_metadata,
            "test-part",
            "non-existent",
            workdir=".",
        )

        self.assertThat(raised.path, Equals("non-existent"))
