# -*- coding: utf-8 -*-
#
# parselglossy -- Generic input parsing library, speaking in tongues
# Copyright (C) 2020 Roberto Di Remigio, Radovan Bast, and contributors.
#
# This file is part of parselglossy.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# For information on the complete list of contributors to the
# parselglossy library, see: <http://parselglossy.readthedocs.io/>
#

"""Documentation generation."""

from typing import List  # noqa: F401

from .utils import JSONDict


def documentation_generator(
    template: JSONDict, *, header: str = "Input parameters"
) -> str:
    """Generates documentation from a valid template.

    Parameters
    ----------
    template : JSONDict
        The template to generate documentation from.
        We assume that the template is valid.

    Returns
    -------
    documentation : str
    """

    comment = (
        ".. raw:: html\n\n"  # noqa: F541
        "    <style> .red {color:#aa0060; font-weight:bold; font-size:18px} </style>\n\n"  # noqa: E501
        ".. role:: red\n\n"
        f".. This documentation was autogenerated using parselglossy."
        " Editing by hand is not recommended.\n"
    )

    header = (
        f"{comment:s}\n{'=' * len(header):s}\n{header:s}\n{'=' * len(header):s}\n\n"
        "- Keywords without a default value are **required**.\n"
        "- Default values are either explicit or computed from the value of other keywords in the input.\n"  # noqa: E501
        "- Sections where all keywords have a default value can be omitted.\n"
        "- Predicates, if present, are the functions run to validate user input.\n"
    )

    docs = _rec_documentation_generator(template=template)

    documentation = header + docs

    return documentation


def _document_keyword(keyword: JSONDict) -> str:
    docstring = keyword["docstring"].replace("\n", " ")
    doc = f"""
 :{keyword['name']:s}: {docstring:s}

  **Type** ``{keyword['type']:s}``
"""

    if "default" in keyword.keys():
        doc += f"""
  **Default** ``{keyword['default']}``
"""

    if "predicates" in keyword.keys():
        preds = "\n    ".join((f"- ``{x}``" for x in keyword["predicates"]))
        doc += f"""
  **Predicates**
    {preds}
"""

    return doc


def _rec_documentation_generator(template, *, level: int = 0) -> str:
    """Generates documentation from a valid template.

    Parameters
    ----------
    template : JSONDict
    level : int

    Returns
    -------
    docs : str
    """

    docs = []  # type: List[str]

    keywords = template["keywords"] if "keywords" in template.keys() else []
    if keywords:
        docs.append(_indent("\n:red:`Keywords`", level))

    for k in keywords:
        doc = _document_keyword(k)
        docs.extend(_indent(doc, level))

    sections = template["sections"] if "sections" in template.keys() else []
    if sections:
        docs.append(_indent("\n:red:`Sections`", level))
        for s in sections:
            docstring = s["docstring"].replace("\n", " ")
            doc = f"\n :{s['name']:s}: {docstring:s}\n"
            doc += _rec_documentation_generator(s, level=level + 1)
            docs.extend(_indent(doc, level))

    return "".join(docs)


def _indent(in_str: str, level: int = 0) -> str:
    return in_str.replace("\n", "\n" + ("  " * level))
