#!/usr/bin/env python3

import cpl
import os
import sys
import re

rst_template = '''The {recipe} recipe
===============================================================

.. data:: {recipe}

Synopsis
--------

{synopsis}

Description
-----------

{description}

Constructor
-----------

.. method:: cpl.Recipe("{recipe}")
   :noindex:

   Create an object for the recipe {recipe}.

::

   import cpl
   {recipe} = cpl.Recipe("{recipe}")

{parameters}

.. seealso:: `cpl.Recipe <https://packages.python.org/python-cpl/recipe.html>`_
   for more information about the recipe object.

Bug reports
-----------

Please report any problems to `{author} <{email}>`_. Alternatively, you may 
send a report to the `ESO User Support Department <usd-help@eso.org>`_.

Copyright
---------

{license}

.. codeauthor:: {author} <{email}>
'''

par_template = '''.. py:attribute:: {recipe}.param.{par}

    {description} [default={default}].
'''

fname_template ="{recipe}.rst"

index_template = '''.. title:: Overview

The {PIPELINE} {version} pipeline
###################################

These pages describe the python interface for the {PIPELINE} pipeline recipes.

{recipes}

.. toctree::
   :hidden:

{toctree}

.. seealso::

     * The `{PIPELINE} Pipeline User Manual 
       <ftp://ftp.eso.org/pub/dfs/pipelines/{pipeline}/{pipeline}-pipeline-manual-1.2.3.pdf>`_ in PDF format,

     * an `overview <https://www.eso.org/sci/software/pipelines/>`_
       over the existing ESO pipelines,

     * the `python-cpl <https://packages.python.org/python-cpl>`_ package.
    
Bug reports
===========

If you experience an unexpected behavior of any component of the {PIPELINE}
pipeline recipes package, please, first refer to the list of known problems
and limitations in the pipeline manual of the current {PIPELINE} pipeline
release.

For any other issues or requests, please, send a report to the `ESO User
Support Department <usd-help@eso.org>`_, describing:

 * the {PIPELINE} pipeline version,
 * the version of your OS and C compiler,
 * the exact sequence of actions that were performed before the problem occurred,
 * what were precisely the symptoms and the possible error message(s),
 * whether the problem is repeatable.
'''

rst_partemplate = '''Parameters
----------

{pars}

The following code snippet shows the default settings for the available 
parameters.

::

   import cpl
   {recipe} = cpl.Recipe("{recipe}")

{pars_example1}

You may also set or overwrite some or all parameters by the recipe 
parameter `param`, as shown in the following example:

::

   import cpl
   {recipe} = cpl.Recipe("{recipe}")
   [...]
   res = {recipe}( ..., param = {{{pars_example2}}})
'''

conf_template = '''project = u'{PIPELINE} pipeline'
version = '{version}'
release = '{version}'
master_doc = 'index'
show_authors = True
html_theme = 'sphinxdoc'
'''

pipeline = sys.argv[1]

cpl.Recipe.path = "recipes"
recipes = [ cpl.Recipe(name) for name, version in cpl.Recipe.list() ]
oca = open(os.path.join("calib", "gasgano", "config", pipeline + ".oca")).read()
oca = oca[oca.find("action"):]
recipes_oca = [recipe for recipe in recipes if recipe.__name__ in oca]
recipes_oca.sort(key = lambda x: x.__name__)

recipes_x = [recipe for recipe in recipes if not recipe.__name__ in oca]
recipes_x.sort(key = lambda x: x.__name__)

def par(recipe, template, delimiter = "", count = None):
    return delimiter.join(template.format(
        recipe = recipe.__name__,
        par = p.name.replace("-","_"),
        type = p.type.__name__,
        description = p.__doc__.replace("\n", "  "),
        default = '"{0}"'.format(p.default) if p.type is str else p.default
    ) for i, p in enumerate(recipe.param) if count is None or i < count)

def get_description(s):
    o = []
    l = s.splitlines()
    enabled = True
    in_code = False
    for i, s in enumerate(l):
        if "BASIC PARAMETERS" in s:
            enabled = False
        elif "Examples:" in s:
            enabled = False
        elif not enabled:
            continue
        elif "-"*40 in s:
            pass
        elif len(s) == 0:
            o += [ "" ]
        elif (s[-1] == "." or s[-1] == ":")and not in_code:
            o += [ s, "" ]
        elif " : " in s or (s.startswith(" ") and '   ' in s):
            if not in_code:
                o += ["::", ""]
            in_code = True
            o += [ "  " + s ]
        elif in_code and s.startswith(" "):
            o += [ "  " + s ]
        else:
            in_code = False
            o += [ s ]
    return "\n".join(o)

def rstpage(recipe, template, partemplate):
    return template.format(
        recipe = recipe.__name__,
        version = recipe.__version__,
        synopsis = recipe.description[0],
        description = get_description(recipe.description[1]),
        email = recipe.__email__,
        author = recipe.__author__,
        license = recipe.__copyright__,
        pipeline = pipeline,
        parameters = partemplate.format(
            recipe = recipe.__name__,
            pars = par(recipe, par_template),
            pars_example1 = par(recipe,
                                '   {recipe}.param.{par} = {default}\n'),
            pars_example2 = par(recipe, '"{par}":{default}', ', ', 2)
        ) if len(recipe.param) > 0 else ''
    )

for recipe in recipes_oca + recipes_x:
    f = open(os.path.join("sphinx",
                          fname_template.format(recipe = recipe.__name__)), "w")
    f.write(rstpage(recipe, rst_template, rst_partemplate))
    f.close()

if len(recipes_oca) > 0 and len(recipes_x) > 0:
    toc_recipes = "Standard recipes\n----------------\n"

toc_recipes += "\n\n".join(":data:`{recipe}`\n   {synopsis}".format(
    recipe = recipe.__name__,
    synopsis = recipe.description[0]
) for recipe in recipes_oca)

if len(recipes_oca) > 0 and len(recipes_x) > 0:
    toc_recipes += "\n\nAdditional recipes\n--------------------\n"

toc_recipes += "\n\n".join(":data:`{recipe}`\n   {synopsis}".format(
    recipe = recipe.__name__,
    synopsis = recipe.description[0]
) for recipe in recipes_x)

toc = "\n".join("   {recipe}".format(
    recipe = recipe.__name__
) for recipe in recipes_oca + recipes_x)

f = open(os.path.join("sphinx", "index.rst"), "w")
f.write(index_template.format(toctree = toc,
                              recipes = toc_recipes,
                              pipeline = pipeline,
                              PIPELINE = pipeline.upper(),
                              version = recipes[0].__version__))
f.close()

f = open(os.path.join("sphinx", "conf.py"), "w")
f.write(conf_template.format(PIPELINE = pipeline.upper(),
                             version = recipes[0].__version__))
f.close()

