#!/usr/bin/env python
# coding=utf-8
#
# Copyright (C) 2019 Marc Jeanmougin
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
#
"""
Generate Latex via a PDF using pdflatex
"""

import os

import inkex
from inkex.base import TempDirMixin
from inkex.command import ProgramRunError, call, inkscape
from inkex import load_svg, ShapeElement, Defs
from inkex.units import convert_unit
from inkex.localization import inkex_gettext as _


class PdfLatex(TempDirMixin, inkex.GenerateExtension):
    """
    Use pdflatex to generate LaTeX, this whole hack is required because
    we don't want to open a LaTeX document as a document, but as a
    generated fragment (like import, but done manually).
    """

    def add_arguments(self, pars):
        pars.add_argument(
            "--formule",
            type=str,
            default=r"\(\displaystyle\frac{\pi^2}{6}=\lim_{n \to \infty}\sum_{k=1}^n \frac{1}{k^2}\)",
        )
        pars.add_argument(
            "--preamble",
            type=str,
            default="".join(
                f"\\usepackage{{ams{i}}}" for i in ["math", "symb", "fonts"]
            ),
        )
        pars.add_argument("--font_size", type=int, default=10)
        pars.add_argument("--page", choices=["basic", "advanced"])
        pars.add_argument("--standalone", type=inkex.Boolean, default=True)

    def generate(self):
        tex_file = os.path.join(self.tempdir, "input.tex")
        pdf_file = os.path.join(self.tempdir, "input.pdf")  # Auto-generate by pdflatex
        svg_file = os.path.join(self.tempdir, "output.svg")

        with open(tex_file, "w") as fhl:
            self.write_latex(fhl)

        try:
            call(
                "pdflatex",
                tex_file,
                output_directory=self.tempdir,
                halt_on_error=True,
                oldie=True,
            )
        except ProgramRunError as err:
            inkex.errormsg(_("An exception occurred during LaTeX compilation: ") + "\n")
            inkex.errormsg(err.stdout.decode("utf8").replace("\r\n", "\n"))
            raise inkex.AbortExtension()

        inkscape(
            pdf_file,
            export_filename=svg_file,
            pdf_page=1,
            pdf_poppler=True,
            export_type="svg",
            actions=(
                "select-all;page-fit-to-selection;"
                "clone-unlink-recursively;vacuum-defs"
            ),
        )

        if not os.path.isfile(svg_file):
            fn = os.path.basename(svg_file)
            if os.path.isfile(fn):
                # Inkscape bug detected, file got saved wrong
                svg_file = fn

        with open(svg_file, "r") as fhl:
            svg: inkex.SvgDocumentElement = load_svg(fhl).getroot()

            scale = convert_unit("1pt", "px") / self.svg.scale
            if not self.options.standalone:
                scale *= self.options.font_size / 10

            for child in svg:
                if isinstance(child, ShapeElement):
                    child.transform = inkex.Transform(scale=scale) @ child.transform
                    yield child
                elif isinstance(child, Defs):
                    for def_child in child:
                        # The ids of both the imported and the target document should
                        # be off-limits
                        def_child.set_random_ids(
                            backlinks=True, blacklist=self.svg.get_ids()
                        )
                        self.svg.defs.append(def_child)

    def write_latex(self, stream):
        """Takes a formula and wraps it in latex"""
        if self.options.standalone:
            docclass = (
                f"\\documentclass[fontsize={self.options.font_size}pt, "
                + "class=scrreprt, preview]{standalone}"
            )
        else:
            docclass = r"\documentclass{minimal}"
        stream.write(
            f"""%% processed with pdflatex.py
{docclass}
{self.options.preamble}
\\begin{{document}}
{self.options.formule}
\\end{{document}}
"""
        )
        stream.flush()


if __name__ == "__main__":
    PdfLatex().run()
