#!/usr/bin/env python
# File created on 15 Feb 2010
from __future__ import division

__author__ = "Jesse Stombaugh"
__copyright__ = "Copyright 2013, The BiPy Project"
__credits__ = ["Jesse Stombaugh",
               "Greg Caporaso"]
__license__ = "GPL"
__version__ = "0.1.0"
__maintainer__ = "Jesse Stombaugh"
__email__ = "gregcaporaso@gmail.com"

import os
from os import makedirs
from os.path import exists, abspath, split, splitext
from string import replace
import types
import re
from sys import exit, stderr
from site import addsitedir
from qcli import (parse_command_line_parameters, 
                  make_option)

rst_text= \
'''\
.. _%s:

.. index:: %s.py

*%s.py* -- %s
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

**Description:**

%s


**Usage:** :file:`%s.py [options]`

**Input Arguments:**

.. note::

%s

**Output:**

%s

%s

'''

script_info={}
script_info['brief_description']="""Make Sphinx RST file for one or more qcli-based scripts"""
script_info['script_description'] = """This script will take a qcli script and convert the usage strings and options to generate a documentation .rst file."""
script_info['script_usage']=[]
script_info['script_usage'].append(("""Create RST for many files""",
                                    """Create rst files for all files ending with .py in the scripts/ directory. Write the rst files to the rst directory. Note that if the value you pass for -i contains a wildcard character (e.g., "*"), the value must be wrapped in quotes.""",
                                    """%prog -i "scripts/*py" -o rst"""))
script_info['output_description']="""This script will output one or more Sphinx rst-formatted files."""

script_info['required_options'] = [
 make_option('-i','--input_fps',type='existing_filepaths',
             help='the input file(s) to generate rst files for'),
 make_option('-o','--output_dir',type='new_filepath',
             help='the directory where the resulting rst file(s) should be written'),
]

script_info['version'] = __version__


def convert_py_file_to_link(input_str):
    m=re.compile('[\w]+\.py')
    python_script_names=set(m.findall(input_str))
    
    if python_script_names:
        script_w_link=input_str
        for i in python_script_names:
            individual_script_name=os.path.splitext(i)
            script_w_link=script_w_link.replace(i, '`'+ i + ' <./' + \
                           individual_script_name[0] + '.html>`_')
        
        return script_w_link
    else:
        return input_str

def main():
    option_parser, opts, args = parse_command_line_parameters(**script_info)

    #Create a list of the scripts to create rst files for.
    file_names = opts.input_fps
    for fn in file_names:
        addsitedir(abspath(split(fn)[0]))
    
    #Identify the directory where results should be written.
    output_dir = opts.output_dir
    if output_dir and not output_dir.endswith('/'):
        output_dir = output_dir + '/'
    if not exists(output_dir):
        makedirs(output_dir)

    script={}
    #Iterate through list of filenames
    for filename in file_names:
        #Get only the name of the script and remove other path information.
        filename = splitext(split(filename)[1])[0]

        #Import the script file to get the dictionary values
        try:
            script=__import__(filename)
        except ImportError:
            raise ImportError, "Can't import %s" % filename
        
        #Define output file path
        outf=os.path.join(output_dir,'%s.rst' % filename)
        
        #This try block attempts to parse the dictionary and if the dictionary
        #is not present, then it will write that information to stdout
        try:

            imported_brief_description=script.script_info['brief_description']
            imported_script_description=script.script_info['script_description']

            new_script_description = \
                    convert_py_file_to_link(imported_script_description)
            #print new_script_description
            inputs=''
            if script.script_info.has_key('required_options') and \
             script.script_info['required_options']<>[]:
                inputs= '\t\n\t**[REQUIRED]**\n\t\t\n'
                for i in script.script_info['required_options']:
                    # when no default is provided in the call to make_option,
                    # the value of i.default is a tuple -- this try/except
                    # handles the diff types that i.default can be
                    try:
                        if i.default<>'':
                            if i.default[0] == 'NO':
                                # i.default is a tuple, so defualt hasn't been
                                # set by the user, and it should therefore be 
                                # None
                                defaults = None
                            else:
                                # i.default is a string
                                defaults = i.default
                        else:
                            defaults=None
                    except TypeError:
                        # i.default is not a string or a tuple (e.g., it's an 
                        # int or None)
                        defaults = i.default
            
                    p=re.compile('\%default')
                    help_str=p.sub(str(defaults),i.help)
                    new_help_str=convert_py_file_to_link(help_str)
                    new_help_str=new_help_str[0].upper() + new_help_str[1:]
        
                    cmd_arg=str(i).replace('--','`-`-').replace('/',', ')
                    inputs=inputs+'\t'+str(cmd_arg)+'\n\t\t'+ new_help_str+'\n'
                    
                    
            if script.script_info.has_key('optional_options') and  \
             script.script_info['optional_options']<>[]:
                inputs=inputs + '\t\n\t**[OPTIONAL]**\n\t\t\n'
                for i in script.script_info['optional_options']:
                    # when no default is provided in the call to make_option,
                    # the value of i.default is a tuple -- this try/except
                    # handles the diff types that i.default can be
                    try:
                        if i.default<>'':
                            if i.default[0] == 'NO':
                                # i.default is a tuple, so defualt hasn't been
                                # set by the user, and it should therefore be 
                                # None
                                defaults = None
                            else:
                                # i.default is a string
                                defaults = i.default
                        else:
                            defaults=i.default
                    except TypeError:
                        # i.default is not a string or a tuple (e.g., it's an 
                        # int or None)
                        defaults = i.default
            
                    p=re.compile('\%default')
                    help_str=p.sub(str(defaults),i.help)
                    new_help_str=convert_py_file_to_link(help_str)
                    new_help_str=new_help_str[0].upper() + new_help_str[1:]
                    
                    cmd_arg=str(i).replace('--','`-`-').replace('/',', ')
                    inputs=inputs+'\t'+str(cmd_arg)+'\n\t\t'+ new_help_str+'\n'

            if (not script.script_info.has_key('required_options') and not script.script_info.has_key('optional_options')) or \
                (script.script_info['required_options']==[] and script.script_info['optional_options']==[]):
                inputs='\t\n\tNone'
                
            script_examples=''
            for ex in script.script_info['script_usage']:
                example_title=ex[0].strip()
                if example_title <> '':
                    if example_title.endswith(':'):
                        script_examples += '\n**' + ex[0] + '**\n'
                    else:
                        script_examples += '\n**' + ex[0] + ':**\n'
                if ex[1] <> '':
                    script_ex=convert_py_file_to_link(ex[1])
                    script_examples += '\n' + script_ex + '\n'
                if ex[2] <>'':
                    new_cmd=ex[2].replace('%prog',filename+'.py')
                    script_examples += '\n::\n\n\t' + new_cmd + '\n'
    
            script_out = \
                  script.script_info['output_description'].replace('--','`-`-')
            new_script_out=convert_py_file_to_link(script_out)

            output_text = rst_text % (filename,
                                      filename,
                                      filename,
                                      imported_brief_description,
                                      new_script_description,
                                      filename,
                                      inputs,
                                      new_script_out,
                                      script_examples)

            ###Write rst file
            f = open(outf, 'w')
            f.write((output_text.replace('%prog',filename+'.py')))
            f.close()
            
            #script.close()
        except AttributeError:
            print "%s: This file does not contain the appropriate dictionary" \
            % (filename)
        except KeyError:
            print "%s: This file does not contain necessary fields" \
            % (filename)


if __name__ == "__main__":
    main()