#!/usr/bin/env python3
# :Copyright: © 2024 Günter Milde.
# :License: Released under the terms of the `2-Clause BSD license`_, in short:
#
#    Copying and distribution of this file, with or without modification,
#    are permitted in any medium without royalty provided the copyright
#    notice and this notice are preserved.
#    This file is offered as-is, without any warranty.
#
# .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause

"""Create output samples for TeX to MathML conversion.

Allows to compare the results of the various converters and Docutils' built-in
convert in web browsers.
"""

from pathlib import Path
import sys
import unittest

# Testing the conversion with external converters requires additional
# ressources (latexml, blahtexml, ttm, pandoc) and is SLOW
# (ca. 27s without testing "latexml" and 13 min with "latexml").
# Therefore, tests are skipped unless run as stand-alone module:

if __name__ != '__main__':
    raise unittest.SkipTest('run stand-alone to test external math converters')
else:
    # prepend the "docutils root" to the Python library path
    # so we import the local `docutils` package.
    sys.path.insert(0, str(Path(__file__).resolve().parents[3]))


from docutils.core import publish_parts, publish_file
from docutils.utils import relative_path

from test.test_functional import compare_output

TEST_ROOT = Path(__file__).parents[2]
DOCS = TEST_ROOT.parent / 'docs'
FUNCTIONAL = TEST_ROOT / 'functional'
EXPECTED = FUNCTIONAL / 'expected'
INPUT = FUNCTIONAL / 'input'
OUTPUT = FUNCTIONAL / 'output'


buggy_sample = r"""
There is ":math:`\lambda\omega\tau\varsigma`" to math.

======================  ========== =======
Das ist nicht lustig.   Dafür das  hier

.. math:: So \isses
======================  ========== =======


Das ist :math:`\ein` Fehler.

.. math:: \int_{-\infty} 3 \sin x} \phy \, d\gamma

.. sidebar:: nebenbemerkung

   noch was :math:`\sqrt[2]`

.. math:: \sqrt[2]

2-zeilig mit align:

.. math::
          s_i     & = 3 \\
          s_j + 3 &

"""


math_options = [('mathml', ''),
                ('mathml', 'ttm'),
                ('mathml', 'blahtexml'),
                ('mathml', 'pandoc'),
                # ('mathml', 'latexml'),  # VERY slow (up to 20 min)
                ]


class MathMLConverterTestCase(unittest.TestCase):
    """
    Functional tests of TeX to MathML converters.

    PROVISIONAL: This class tests a provisional implementation
    which is open to change without warning.
    """
    settings = {'_disable_config': True,
                'input_encoding': 'utf-8',  # skip auto-detection
                'embed_stylesheet': False,
                'warning_stream': '',
                'report_level': 2,  # warning
                # 'report_level': 3,  # error
                # 'report_level': 4,  # severe
                }

    def test_mathematics(self):
        """Test converting "mathematics.rst" from the documentation."""

        source_path = relative_path(None, DOCS/'ref'/'rst'/'mathematics.rst')

        for math_output in math_options:
            settings = {'math_output': math_output,
                        'stylesheet_path': 'minimal.css,responsive.css',
                        **self.settings}
            out_file = f'mathematics_{"_".join(math_output).strip("_")}.html'
            out_path = OUTPUT / out_file
            expected_path = EXPECTED / out_file
            output = publish_file(source_path=str(source_path),
                                  destination_path=out_path.as_posix(),
                                  writer='html5',
                                  settings_overrides=settings)
            with self.subTest(converter=math_output[1] or 'latex2mathml()'):
                compare_output(output, out_path, expected_path)

    def test_math_experiments(self):
        """Convert experimental math sample."""

        source_path = relative_path(None, INPUT/'data'/'math_experiments.rst')

        for math_output in math_options:
            settings = {'math_output': math_output, **self.settings}
            out_file = f'math_experiments_{"_".join(math_output).strip("_")}.html'  # noqa: E501
            out_path = OUTPUT / out_file
            expected_path = EXPECTED / out_file
            output = publish_file(source_path=str(source_path),
                                  destination_path=out_path.as_posix(),
                                  writer='html5',
                                  settings_overrides=settings)
            with self.subTest(converter=math_output[1] or 'latex2mathml()'):
                compare_output(output, out_path, expected_path)

    def test_buggy_math(self):
        """Test reporting conversion failure due to TeX-syntax errors."""

        for math_output in math_options:
            settings = {'math_output': math_output, **self.settings}
            out_file = f'buggy_{"_".join(math_output).strip("_")}.html'
            out_path = OUTPUT / out_file
            expected_path = EXPECTED / out_file
            preface = f'Test "math-output: {" ".join(math_output)}".\n\n'
            parts = publish_parts(preface + buggy_sample,
                                  'buggy-maths',
                                  writer='html5',
                                  settings_overrides=settings)
            Path(out_path).write_text(parts['whole'])
            with self.subTest(converter=math_output[1] or 'latex2mathml()'):
                compare_output(parts['whole'], out_path, expected_path)


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