#!/usr/bin/python3

import subprocess
import sys

from docutils import nodes, core
from docutils.parsers.rst import directives, Directive


class Chroma(Directive):
    """Source code syntax highlighting."""

    required_arguments = 1
    optional_arguments = 0
    final_argument_whitespace = True
    option_spec = {}
    has_content = True

    def run(self):
        self.assert_has_content()
        data = "\n".join(self.content)
        try:
            parsed = subprocess.run(
                ["{{ gitea.lookup.mod_rst.chroma_bin }}", "--html", "--html-only", "-l", self.arguments[0]],
                text=True,
                input=data,
                capture_output=True,
                check=True,
            )
        except subprocess.CalledProcessError:
            parsed = subprocess.run(
                ["{{ gitea.lookup.mod_rst.chroma_bin }}", "--html", "--html-only"],
                text=True,
                input=data,
                capture_output=True,
                check=True,
            )

        return [nodes.raw("", parsed.stdout, format="html")]


def html_parts(
    input_string,
    source_path=None,
    destination_path=None,
    input_encoding="utf8",
    doctitle=True,
    initial_header_level=1,
):
    """
    Given an input string, returns a dictionary of HTML document parts.

    Dictionary keys are the names of parts, and values are Unicode strings;
    encoding is up to the client.

    Parameters:

    - `input_string`: A multi-line text string; required.
    - `source_path`: Path to the source file or object.  Optional, but useful
      for diagnostic output (system messages).
    - `destination_path`: Path to the file or object which will receive the
      output; optional.  Used for determining relative paths (stylesheets,
      source links, etc.).
    - `input_encoding`: The encoding of `input_string`.  If it is an encoded
      8-bit string, provide the correct encoding.  If it is a Unicode string,
      use "unicode", the default.
    - `doctitle`: Disable the promotion of a lone top-level section title to
      document title (and subsequent section title to document subtitle
      promotion); enabled by default.
    - `initial_header_level`: The initial level for header elements (e.g. 1
      for "<h1>").
    """
    overrides = {
        "input_encoding": input_encoding,
        "doctitle_xform": doctitle,
        "initial_header_level": initial_header_level,
        "report_level": 4,
    }

    parts = core.publish_parts(
        source=input_string,
        source_path=source_path,
        destination_path=destination_path,
        writer_name="html",
        settings_overrides=overrides,
    )
    return parts


def html_body(
    input_string,
    source_path=None,
    destination_path=None,
    input_encoding="utf8",
    output_encoding="unicode",
    doctitle=True,
    initial_header_level=1,
):
    """
    Given an input string, returns an HTML fragment as a string.

    The return value is the contents of the <body> element.

    Parameters (see `html_parts()` for the remainder):

    - `output_encoding`: The desired encoding of the output.  If a Unicode
      string is desired, use the default value of "unicode" .
    """
    parts = html_parts(
        input_string=input_string,
        source_path=source_path,
        destination_path=destination_path,
        input_encoding=input_encoding,
        doctitle=doctitle,
        initial_header_level=initial_header_level,
    )
    fragment = parts["html_body"]
    if output_encoding != "unicode":
        fragment = fragment.encode(output_encoding)
    return fragment


if __name__ == "__main__":
    directives.register_directive("code-block", Chroma)

    with open(sys.argv[1], "r") as f:
        source = "".join(f.readlines())
    print(html_body(source.encode()))
