"""Input/Output files"""
from __future__ import annotations

from typing import TYPE_CHECKING, Any

import docutils
from docutils import nodes
from docutils.core import Publisher
from docutils.io import FileInput, Input, NullOutput
from docutils.readers import standalone
from docutils.transforms.references import DanglingReferences
from docutils.writers import UnfilteredWriter

from sphinx import addnodes
from sphinx.transforms import AutoIndexUpgrader, DoctreeReadEvent, SphinxTransformer
from sphinx.transforms.i18n import (
    Locale,
    PreserveTranslatableMessages,
    RemoveTranslatableInline,
)
from sphinx.transforms.references import SphinxDomains
from sphinx.util import logging
from sphinx.util.docutils import LoggingReporter
from sphinx.versioning import UIDTransform

if TYPE_CHECKING:
    from docutils.frontend import Values
    from docutils.parsers import Parser
    from docutils.transforms import Transform

    from sphinx.application import Sphinx
    from sphinx.environment import BuildEnvironment


logger = logging.getLogger(__name__)


class SphinxBaseReader(standalone.Reader):
    """
    A base class of readers for Sphinx.

    This replaces reporter by Sphinx's on generating document.
    """

    transforms: list[type[Transform]] = []

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        from sphinx.application import Sphinx
        if len(args) > 0 and isinstance(args[0], Sphinx):
            self._app = args[0]
            self._env = self._app.env
            args = args[1:]

        super().__init__(*args, **kwargs)

    def setup(self, app: Sphinx) -> None:
        self._app = app      # hold application object only for compatibility
        self._env = app.env

    def get_transforms(self) -> list[type[Transform]]:
        transforms = super().get_transforms() + self.transforms

        # remove transforms which is not needed for Sphinx
        unused = [DanglingReferences]
        for transform in unused:
            if transform in transforms:
                transforms.remove(transform)

        return transforms

    def new_document(self) -> nodes.document:
        """
        Creates a new document object which has a special reporter object good
        for logging.
        """
        document = super().new_document()
        document.__class__ = addnodes.document  # replace the class with patched version

        # substitute transformer
        document.transformer = SphinxTransformer(document)
        document.transformer.set_environment(self.settings.env)

        # substitute reporter
        reporter = document.reporter
        document.reporter = LoggingReporter.from_reporter(reporter)

        return document


class SphinxStandaloneReader(SphinxBaseReader):
    """
    A basic document reader for Sphinx.
    """

    def setup(self, app: Sphinx) -> None:
        self.transforms = self.transforms + app.registry.get_transforms()
        super().setup(app)

    def read(self, source: Input, parser: Parser, settings: Values) -> nodes.document:
        self.source = source
        if not self.parser:
            self.parser = parser
        self.settings = settings
        self.input = self.read_source(settings.env)
        self.parse()
        return self.document

    def read_source(self, env: BuildEnvironment) -> str:
        """Read content from source and do post-process."""
        content = self.source.read()

        # emit "source-read" event
        arg = [content]
        env.events.emit('source-read', env.docname, arg)
        return arg[0]


class SphinxI18nReader(SphinxBaseReader):
    """
    A document reader for i18n.

    This returns the source line number of original text as current source line number
    to let users know where the error happened.
    Because the translated texts are partial and they don't have correct line numbers.
    """

    def setup(self, app: Sphinx) -> None:
        super().setup(app)

        self.transforms = self.transforms + app.registry.get_transforms()
        unused = [PreserveTranslatableMessages, Locale, RemoveTranslatableInline,
                  AutoIndexUpgrader, SphinxDomains, DoctreeReadEvent,
                  UIDTransform]
        for transform in unused:
            if transform in self.transforms:
                self.transforms.remove(transform)


class SphinxDummyWriter(UnfilteredWriter):
    """Dummy writer module used for generating doctree."""

    supported = ('html',)  # needed to keep "meta" nodes

    def translate(self) -> None:
        pass


def SphinxDummySourceClass(source: Any, *args: Any, **kwargs: Any) -> Any:
    """Bypass source object as is to cheat Publisher."""
    return source


class SphinxFileInput(FileInput):
    """A basic FileInput for Sphinx."""
    def __init__(self, *args: Any, **kwargs: Any) -> None:
        kwargs['error_handler'] = 'sphinx'
        super().__init__(*args, **kwargs)


def create_publisher(app: Sphinx, filetype: str) -> Publisher:
    reader = SphinxStandaloneReader()
    reader.setup(app)

    parser = app.registry.create_source_parser(app, filetype)
    if parser.__class__.__name__ == 'CommonMarkParser' and parser.settings_spec == ():
        # a workaround for recommonmark
        #   If recommonmark.AutoStrictify is enabled, the parser invokes reST parser
        #   internally.  But recommonmark-0.4.0 does not provide settings_spec for reST
        #   parser.  As a workaround, this copies settings_spec for RSTParser to the
        #   CommonMarkParser.
        from docutils.parsers.rst import Parser as RSTParser

        parser.settings_spec = RSTParser.settings_spec

    pub = Publisher(
        reader=reader,
        parser=parser,
        writer=SphinxDummyWriter(),
        source_class=SphinxFileInput,
        destination=NullOutput(),
    )
    # Propagate exceptions by default when used programmatically:
    defaults = {"traceback": True, **app.env.settings}
    # Set default settings
    if docutils.__version_info__[:2] >= (0, 19):
        pub.get_settings(**defaults)
    else:
        pub.settings = pub.setup_option_parser(**defaults).get_default_values()
    return pub
