import datetime
import sys
from pyautodoc.utils.stringify import generate_mocks_stuff, convert_path

autodoc_default_options = """{
    'members': True,
    'member-order': 'bysource',
    'special-members': '',
    'undoc-members': False,
    'exclude-members': ''
}"""


def generate_config_file(root_folder, project_name, author, version, language_locale, file_path, html_options=None,
                         latex_options=None, mocks_imports=None, extra_extensions=None):
    """
    Genera el fichero de configuración necesario para sphinx

    :param str root_folder: ruta de la carpeta raíz del proyecto a documentar
    :param str project_name: nombre del proyecto
    :param str author: autor
    :param str version: versión del proyecto
    :param str language_locale: código lingüístico del país
    :param str file_path: ruta del fichero para guardar
    :param dict html_options: diccionario con las opciones de configuración html para Sphinx
    :param dict latex_options: diccionario con las opciones de configuración LaTeX para Sphinx
    :param list mocks_imports: lista de las importaciones que deben ignorarse dentro del ficheros
    :param list extra_extensions: lista con las extensiónes extra de Sphinx
    """
    if mocks_imports is None:
        mocks_imports = []

    if extra_extensions is None:
        extra_extensions = ""
    else:
        extra_extensions = 'extensions.extend(' + generate_mocks_stuff(extra_extensions) + ')'

    template = """
# -- Path setup --------------------------------------------------------------

import os
import sys
sys.path.insert(0, os.path.abspath('{root_folder}'))


# -- Project information -----------------------------------------------------

project = '{project_name}'
copyright = '{copyright}'
author = '{author}'

# The full version, including alpha/beta/rc tags
release = '{version}'

master_doc = 'index'

# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.todo', 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'm2r']
{extra_extensions}
source_suffix = ['.rst', '.md']
# NOTE: Don't overwrite your old extension list! Just add to it!

autodoc_default_options = {autodoc_default_options}
autodoc_mock_imports = {mocks_imports}
autoclass_content = 'both'
autosummary_generate = True

# Add any paths that contain generators here, relative to this directory.
templates_path = ['_templates']

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = '{language_locale}'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
""".format(root_folder=root_folder, project_name=project_name,
           copyright=str(datetime.datetime.now().year) + ', ' + author, author=author, version=version,
           autodoc_default_options=autodoc_default_options, mocks_imports=generate_mocks_stuff(mocks_imports),
           language_locale=language_locale, extra_extensions=extra_extensions)
    template = template + generate_html_config(html_options)
    template = template + generate_latex_config(latex_options)

    with open(file_path, 'w') as f:
        f.write(template)


def generate_html_config(html_options=None):
    """
    Genera la información necesaria para la compilación a HTML

    :param dict html_options: diccionario con las opciones html de Sphinx
    :return: string con la información necesaría para añadir al fichero ```conf.py`` en lo referente a las opciones html
    :rtype: str
    """

    if html_options is None:
        html_options = {}

    template_theme = html_options.get('template_theme', 'alabaster')
    template_options = html_options.get('template_options', {})
    template_import = ''

    extensions = ""
    if html_options.get('template_extensions') is not None:
        extensions = 'extensions.extend(' + generate_mocks_stuff(html_options.get('template_extensions')) + ')'

    if html_options.get('template_package') is not None:
        template_import = 'import ' + html_options.get('template_package')
        try:
            __import__(html_options.get('template_package'))
        except ModuleNotFoundError:
            print('You need to install theme: \"' + html_options.get('template_package') + '\" before runnig the script')
            sys.exit()
    template_path = 'html_theme_path = [' + html_options.get('template_path') + ']' \
        if html_options.get('template_path') is not None else ''

    template = """
# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
{template_import}
html_theme = '{template_theme}'
html_theme_options = {template_options}
{template_path}
{extensions}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
""".format(template_import=template_import, template_theme=template_theme, template_options=str(template_options),
           template_path=template_path, extensions=extensions)

    return template


def generate_latex_config(latex_options=None):
    """
    Genera la información necesaria para la compilación a LaTeX

    :param dict latex_options: diccionario con las opciones LaTeX de Sphinx
    :return: string con la información necesaría para añadir al fichero ```conf.py`` en lo referente a las opciones LaTeX
    :rtype: str

    """
    if latex_options is None:
        return ""
    else:
        latex_template = ""
        for key, value in latex_options.items():
            latex_template = latex_template + key + " = \'" + convert_path(value) + "\'\n"
    return latex_template
