"""Unit testing suite for the Link Class Plugin"""

# Copyright (C) 2015, 2017, 2019, 2021  Rafael Laboissière <rafael@laboissiere.net>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Affero Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# 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
# Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see http://www.gnu.org/licenses/.

# For running this test in a standalone-way, run:
#     (cd .. ; python3 -Wd -m unittest discover)

import os
import re
from shutil import rmtree
import sys
from tempfile import mkdtemp
import unittest

from six import StringIO

from pelican import Pelican
from pelican.settings import read_settings

from . import linkclass

INTERNAL_CLASS = "internal"
EXTERNAL_CLASS = "external"

INTERNAL_INLINE_TEXT = "internal inline text"
INTERNAL_INLINE_LINK = "internal inline link"

INTERNAL_REFERENCE_TEXT = "internal reference text"
INTERNAL_REFERENCE_LABEL = "internal reference label"
INTERNAL_REFERENCE_LINK = "internal-reference-link"

EXTERNAL_INLINE_TEXT_HTTP = "external inline text http"
EXTERNAL_INLINE_LINK_HTTP = "https://inline.org"

EXTERNAL_REFERENCE_TEXT_HTTP = "external reference text http"
EXTERNAL_REFERENCE_LABEL_HTTP = "external reference label http"
EXTERNAL_REFERENCE_LINK_HTTP = "https://reference.org"

EXTERNAL_INLINE_TEXT_HTTPS = "external inline text https"
EXTERNAL_INLINE_LINK_HTTPS = "https://inline.org"

EXTERNAL_REFERENCE_TEXT_HTTPS = "external reference text https"
EXTERNAL_REFERENCE_LABEL_HTTPS = "external reference label https"
EXTERNAL_REFERENCE_LINK_HTTPS = "https://reference.org"

LINK_PATTERN = '<a class="{}" href="{}">{}</a>'

TEST_FILE_STEM = "test"
TEST_DIR_PREFIX = "pelicantests."


class TestLinkClass(unittest.TestCase):
    """Class for testing the <a> output elements generated by the Link Class plugin"""

    def setUp(self, override=None):
        self.output_path = mkdtemp(prefix=TEST_DIR_PREFIX)
        self.content_path = mkdtemp(prefix=TEST_DIR_PREFIX)
        settings = {
            "PATH": self.content_path,
            "OUTPUT_PATH": self.output_path,
            "PLUGINS": [linkclass],
            "CACHE_CONTENT": False,
            "SITEURL": "http://example.org",
            "TIMEZONE": "UTC",
            "LINKCLASS": (
                ("INTERNAL_CLASS", INTERNAL_CLASS, ""),
                ("EXTERNAL_CLASS", EXTERNAL_CLASS, ""),
            ),
        }
        if override:
            settings.update(override)

        # Generate the test Markdown source file
        fid = open(
            os.path.join(self.content_path, "{}.md".format(TEST_FILE_STEM)),
            "w",
        )
        fid.write(
            """Title: Test
Date: 1970-01-01

This is an [{}]({}), inline-style link.
This is an [{}]({}), inline-style link (with http URL).
This is an [{}]({}), inline-style link (with https URL).

This is an [{}][{}], reference-style link.
This is an [{}][{}], reference-style link (with http URL).
This is an [{}][{}], reference-style link (with https URL).

 [{}]: {}
 [{}]: {}
 [{}]: {}

""".format(
                INTERNAL_INLINE_TEXT,
                INTERNAL_INLINE_LINK,
                EXTERNAL_INLINE_TEXT_HTTP,
                EXTERNAL_INLINE_LINK_HTTP,
                EXTERNAL_INLINE_TEXT_HTTPS,
                EXTERNAL_INLINE_LINK_HTTP,
                INTERNAL_REFERENCE_TEXT,
                INTERNAL_REFERENCE_LABEL,
                EXTERNAL_REFERENCE_TEXT_HTTP,
                EXTERNAL_REFERENCE_LABEL_HTTP,
                EXTERNAL_REFERENCE_TEXT_HTTPS,
                EXTERNAL_REFERENCE_LABEL_HTTPS,
                INTERNAL_REFERENCE_LABEL,
                INTERNAL_REFERENCE_LINK,
                EXTERNAL_REFERENCE_LABEL_HTTP,
                EXTERNAL_REFERENCE_LINK_HTTP,
                EXTERNAL_REFERENCE_LABEL_HTTPS,
                EXTERNAL_REFERENCE_LINK_HTTPS,
            )
        )
        fid.close()

        # Run the Pelican instance
        self.settings = read_settings(override=settings)
        pelican = Pelican(settings=self.settings)
        saved_stdout = sys.stdout
        sys.stdout = StringIO()
        pelican.run()
        sys.stdout = saved_stdout

    def tearDown(self):
        """Remove the temporary directories"""
        rmtree(self.output_path)
        rmtree(self.content_path)

    def search(self, string):
        """Search for a string in the article output"""
        fid = open(
            os.path.join(self.output_path, "{}.html".format(TEST_FILE_STEM)),
            "r",
        )
        found = False
        for line in fid.readlines():
            if re.search(string, line):
                found = True
                break
        fid.close()
        return found

    def test_internal_inline(self):
        """Test for the internal inline link"""
        assert self.search(
            LINK_PATTERN.format(
                INTERNAL_CLASS,
                INTERNAL_INLINE_LINK,
                INTERNAL_INLINE_TEXT,
            )
        )

    def test_external_inline_http(self):
        """Test for the external http inline link"""
        assert self.search(
            LINK_PATTERN.format(
                EXTERNAL_CLASS,
                EXTERNAL_INLINE_LINK_HTTP,
                EXTERNAL_INLINE_TEXT_HTTP,
            )
        )

    def test_external_inline_https(self):
        """Test for the external https inline link"""
        assert self.search(
            LINK_PATTERN.format(
                EXTERNAL_CLASS,
                EXTERNAL_INLINE_LINK_HTTPS,
                EXTERNAL_INLINE_TEXT_HTTPS,
            )
        )

    def test_internal_reference(self):
        """Test for the internal reference link"""
        assert self.search(
            LINK_PATTERN.format(
                INTERNAL_CLASS,
                INTERNAL_REFERENCE_LINK,
                INTERNAL_REFERENCE_TEXT,
            )
        )

    def test_external_reference_http(self):
        """Test for the external http reference link"""
        assert self.search(
            LINK_PATTERN.format(
                EXTERNAL_CLASS,
                EXTERNAL_REFERENCE_LINK_HTTP,
                EXTERNAL_REFERENCE_TEXT_HTTPS,
            )
        )

    def test_external_reference_https(self):
        """Test for the external https reference link"""
        assert self.search(
            LINK_PATTERN.format(
                EXTERNAL_CLASS,
                EXTERNAL_REFERENCE_LINK_HTTPS,
                EXTERNAL_REFERENCE_TEXT_HTTPS,
            )
        )
