# SPDX-FileCopyrightText: © 2023 Christian BUHTZ <c.buhtz@posteo.jp>
#
# SPDX-License-Identifier: GPL-3.0-only
#
# This file is part of the program "Hyperorg" which is released under GNU
# General Public License v3 (GPLv3).
# See folder LICENSES or go to <https://www.gnu.org/licenses/#GPL>.
"""Tests about generating HTML using `exporter._html_from_runs()`."""
import unittest
from hyperorg import textruns
from hyperorg import exporter
from hyperorg.content import Node


def _reset_node_class():
    Node.nodes = {}
    Node.heading_ids = {}
    Node.input_dir = 'input_dir'
    exporter.Exporter.output_dir = 'output_dir'


class HtmlFromRuns_Markup(unittest.TestCase):  # pylint: disable=C0103
    """Test HTML out of markup runs"""

    # pylint: disable=protected-access,missing-function-docstring

    def test_no_markup_text(self):
        runs = ['foobar']

        self.assertEqual(exporter._html_from_runs(runs), 'foobar')

    def test_markup(self):
        runs = [
            textruns.Markup('foobar', textruns.Markup.Kind.IMPORTANT)
        ]

        self.assertEqual(
            exporter._html_from_runs(runs),
            '<strong>foobar</strong>')


class HtmlFromRuns_Links(unittest.TestCase):  # pylint: disable=C0103
    """Test HTML out of link runs"""

    # pylint: disable=protected-access,missing-function-docstring

    @classmethod
    def setUpClass(cls):
        # pylint: disable=duplicate-code
        def _mock_me(*args, **kwargs):  # pylint: disable=unused-argument
            pass
        cls._establish_file_link = exporter._establish_file_link
        exporter._establish_file_link = _mock_me

    @classmethod
    def tearDownClass(cls):
        # pylint: disable=duplicate-code
        exporter._establish_file_link = cls._establish_file_link

    def setUp(self):
        _reset_node_class()

    def test_roam(self):
        runs = [
            textruns.Link('roam:123'),
            ' and ',
            textruns.Link('roam:123][with label')
        ]

        expect_html = '<span style="color: DeepPink">💀 roam:123</span>' \
                      ' and <span style="color: DeepPink">💀 with label ' \
                      '(roam:123)</span>'

        self.assertEqual(exporter._html_from_runs(runs), expect_html)

    def test_orgid(self):
        Node.nodes['123'] = Node([], '123_foo.org')
        runs = [
            textruns.Link('id:123][normal'),
            ' and ',
            textruns.Link('id:123][two words'),
            ' and ',
            textruns.Link('id:123][with\nlinebreak'),
        ]

        expect_html = '<a href="123_foo.html">normal</a> and ' \
            '<a href="123_foo.html">two words</a> and ' \
            '<a href="123_foo.html">with\nlinebreak</a>'

        self.assertEqual(exporter._html_from_runs(runs), expect_html)

    def test_orgid_without_label(self):
        Node.nodes['123'] = Node([], '123_foo.org')
        runs = [textruns.Link('id:123')]

        expect_html = '<a href="123_foo.html">123</a>'

        self.assertEqual(exporter._html_from_runs(runs), expect_html)

    def test_orgid_target_dead(self):
        """Org-roam-ID dead links."""
        runs = [textruns.Link('id:123][normal')]
        expect = '<span style="color: red">💀 normal ' \
                 '(UNKNOWN maybe DEAD org-id: 123)</span>'

        self.assertEqual(exporter._html_from_runs(runs), expect)

    def test_https(self):
        """Hyperlinks with and without labels to href."""
        test_data = [
            # Link with label
            ([textruns.Link('https://foo.bar][foobar')],
             '<a target="_blank" rel="noopener noreferrer" '
             'href="https://foo.bar">foobar</a>'),

            # Link without label
            ([textruns.Link('https://foo.bar')],
             '<a target="_blank" rel="noopener noreferrer" '
             'href="https://foo.bar">https://foo.bar</a>'),

            # two links with(out) label
            ([
                textruns.Link('https://foo.bar][foobar'),
                ' and ',
                textruns.Link('https://foo.bar')
             ],
             '<a target="_blank" rel="noopener noreferrer" '
             'href="https://foo.bar">foobar</a> and '
             '<a target="_blank" rel="noopener noreferrer" '
             'href="https://foo.bar">https://foo.bar</a>'),

            # two links other way around
            ([
                textruns.Link('https://foo.bar'),
                ' and ',
                textruns.Link('https://foo.bar][foobar')
             ],
             '<a target="_blank" rel="noopener noreferrer" '
             'href="https://foo.bar">https://foo.bar</a> and '
             '<a target="_blank" rel="noopener noreferrer" '
             'href="https://foo.bar">foobar</a>'),
        ]

        for runs, expect in test_data:
            self.assertEqual(exporter._html_from_runs(runs), expect)

    def test_https_linebreaks(self):
        """Hyperlinks with linebreaks."""
        runs = [textruns.Link('https://foo.bar][foo\nbar')]
        expect = '<a target="_blank" rel="noopener noreferrer" ' \
                 'href="https://foo.bar">foo\nbar</a>'

        self.assertEqual(exporter._html_from_runs(runs), expect)

    def test_doi(self):
        self.assertEqual(
            exporter._html_from_runs(
                [textruns.Link('doi:10.1055/a-1961-1145')]),
            'DOI: <a target="_blank" rel="noopener noreferrer" '
            'href="https://doi.org/10.1055/a-1961-1145">'
            '10.1055/a-1961-1145</a>')

    def test_doi_label(self):
        self.assertEqual(
            exporter._html_from_runs(
                [textruns.Link('doi:10.1055/a-1961-1145][Inanspruchnahme')]),
            '<a target="_blank" rel="noopener noreferrer" '
            'href="https://doi.org/10.1055/a-1961-1145">'
            'Inanspruchnahme</a>')

    def test_mailto(self):
        self.assertEqual(
            exporter._html_from_runs(
                [textruns.Link('mailto:c.buhtz@posteo.jp')]),
            '<a target="_blank" rel="noopener noreferrer" '
            'href="mailto:c.buhtz@posteo.jp">c.buhtz@posteo.jp</a>')

    def test_mailto_label(self):
        self.assertEqual(
            exporter._html_from_runs(
                [textruns.Link('mailto:c.buhtz@posteo.jp][Maintainer')]),
            '<a target="_blank" rel="noopener noreferrer" '
            'href="mailto:c.buhtz@posteo.jp">Maintainer</a>')

    def test_file(self):
        self.assertEqual(
            exporter._html_from_runs(
                [textruns.Link('file:foobar.dat')]),
            '<a target="_blank" rel="noopener noreferrer" '
            'href="foobar.dat">foobar.dat</a>')

    def test_file_label(self):
        self.assertEqual(
            exporter._html_from_runs(
                [textruns.Link('file:foobar.dat][FOOBAR.DAT')]),
            '<a target="_blank" rel="noopener noreferrer" '
            'href="foobar.dat">FOOBAR.DAT</a>')

    def test_no_kind(self):
        self.assertEqual(
            exporter._html_from_runs(
                [textruns.Link('foobar.dat')]),
            '<a target="_blank" rel="noopener noreferrer" '
            'href="foobar.dat">foobar.dat</a>')

    def test_no_kind_label(self):
        self.assertEqual(
            exporter._html_from_runs(
                [textruns.Link('foobar.dat][LaBeL')]),
            '<a target="_blank" rel="noopener noreferrer" '
            'href="foobar.dat">LaBeL</a>')

    def test_unsecure_http(self):
        """HTTP links are not secure but will be parsed.

            See #29 about an improvement of that behavior
            unsafe (because of HTTP-only) hyperlinks not parsed
        """
        runs = [textruns.Link('http://foo.bar')]
        tooltip = 'For security reasons, HTTP URLs are not supported. ' \
                  'Find an alternative HTTPS source.'
        expect = f'<span class="insecure" title="{tooltip}">' \
                 '<del>http</del>://foo.bar</span>'
        self.assertEqual(exporter._html_from_runs(runs), expect)

    def test_unsecure_http_label(self):
        """HTTP links are not secure but will be parsed.

            See #29 about an improvement of that behavior
            unsafe (because of HTTP-only) hyperlinks not parsed
        """
        runs = [textruns.Link('http://foo.bar][foobar')]
        tooltip = 'For security reasons, HTTP URLs are not supported. ' \
                  'Find an alternative HTTPS source.'
        expect = f'<span class="insecure" title="{tooltip}">' \
                 '<del>http</del>://foo.bar "foobar"</span>'
        self.assertEqual(exporter._html_from_runs(runs), expect)


class HtmlFromRuns_InlineImages(unittest.TestCase):  # pylint: disable=C0103
    """Test HTML out of inline images"""
    # pylint: disable=protected-access
    @classmethod
    def setUpClass(cls):
        def _mock_me(*args, **kwargs):  # pylint: disable=unused-argument
            pass
        cls._establish_file_link = exporter._establish_file_link
        exporter._establish_file_link = _mock_me

    @classmethod
    def tearDownClass(cls):
        exporter._establish_file_link = cls._establish_file_link

    def test_inline_image(self):
        """Inline image"""
        sut = [
            'foo',
            textruns.Image('target.png'),
            'bar'
        ]

        self.assertEqual(
            exporter._html_from_runs(sut),
            'foo<img src="target.png" alt="target.png" />bar'
        )

    def test_inline_image_as_link(self):
        """Linked inline image"""
        sut = [
            'foo',
            textruns.Link('target.png][file:image.png'),
            'bar'
        ]

        self.assertEqual(
            exporter._html_from_runs(sut),
            'foo'
            '<a target="_blank" rel="noopener noreferrer" href="target.png">'
            '<img src="image.png" alt="image.png" />'
            '</a>bar'
        )
