# -*- coding: utf-8 -*-
"""
Created on Fri Jun 26 19:10:58 2015

@author: pietro
"""
from __future__ import print_function
import argparse
from pprint import pprint
import sys
from urllib import urlopen


def parse_options(lines):
    def split_in_groups(lines):
        def count_par_diff(line):
            open_par = line.count('(')
            close_par = line.count(')')
            return open_par - close_par
        res = None
        diff = 0
        for line in lines:
            if line.startswith('case'):
                optname = line.split()[1][:-1]
                res = []
            elif line == 'break;':
                yield optname, res
            elif line.startswith('G_'):
                diff = count_par_diff(line)
            elif diff > 0:
                diff -= count_par_diff(line)
            else:
                res.append(line) if res is not None else None

    def split_opt_line(line):
        index = line.index('=')
        key = line[:index].strip()
        default = line[index + 1:].strip()
        if default.startswith('_('):
            default = default[2:]
        return key, default

    def parse_glines(glines):
        res = {}
        key = None
        for line in glines:
            if line.startswith('/*'):
                continue
            if line.startswith('Opt') and line.endswith(';'):
                key, default = [w.strip() for w in split_opt_line(line[5:])]
                res[key] = default
            elif line.startswith('Opt'):
                key, default = split_opt_line(line[5:])
                res[key] = [default, ]
            else:
                if key is not None:
                    if key not in res:
                        res[key] = []
                    start, end = 0, -1
                    if line.startswith('_('):
                        start = 2
                    if line.endswith(');'):
                        end = -3
                    elif line.endswith(';'):
                        end = -2
                    res[key].append(line[start:end])
        # pprint(glines)
        # pprint(res)
        return res

    def clean_value(val):
        if isinstance(val, list):
            val = ' '.join(val)
        return (val.replace('"', '').replace("\'", "'").strip().strip(';')
                ).strip().strip('_(').strip().strip(')').strip()

    # with open(optionfile, mode='r') as optfile:
    lines = [line.strip() for line in lines]
    result = []
    for optname, glines in split_in_groups(lines):
        if glines is not None:
            res = parse_glines(glines)
            # clean description
            for key, val in res.items():
                res[key] = clean_value(val)
            result.append((optname, res))
    return result


class OptTable(object):
    """"""
    def __init__(self, list_of_dict):
        self.options = list_of_dict
        self.columns = sorted(set([key for _, d in self.options
                                   for key in d.keys()]))

    def csv(self, delimiter=';', endline='\n'):
        """Return a CSV string with the options"""
        csv = []
        csv.append(delimiter.join(self.columns))
        for optname, options in self.options:
            opts = [options.get(col, '') for col in self.columns]
            csv.append(delimiter.join([optname, ] + opts))
        return endline.join(csv)

    def html(self, endline='\n', indent='  '):
        """Return a HTML table with the options"""
        html = ["<table>"]
        # write headers
        html.append(indent + "<tr>")
        html.append(indent * 2 + "<td>{0}</td>".format('option'))
        for col in self.columns:
            html.append(indent * 2 + "<td>{0}</td>".format(col))
        html.append(indent + "</tr>")
        for optname, options in self.options:
            html.append(indent + "<tr>")
            html.append(indent * 2 + "<td>{0}</td>".format(optname))
            for col in self.columns:
                html.append(indent * 2 +
                            "<td>{0}</td>".format(options.get(col, '')))
            html.append(indent + "</tr>")
        html.append("</table>")
        return endline.join(html)

    def _repr_html_(self):
        """Method used by IPython notebook"""
        return self.html()


if __name__ == "__main__":
    URL = ('https://trac.osgeo.org/grass/browser/grass/'
           'trunk/lib/gis/parser_standard_options.c?format=txt')
    parser = argparse.ArgumentParser(description='Extract GRASS default '
                                                 'options from link.')
    parser.add_argument('-f', '--format', default='html', dest='format',
                        choices=['html', 'csv'],
                        help='Define the output format')
    parser.add_argument('-l', '--link', default=URL, dest='url', type=str,
                        help='Provide the url with the file to parse')
    parser.add_argument('-t', '--text', default='', dest='text',
                        type=argparse.FileType('r'),
                        help='Provide the file to parse')
    parser.add_argument('-o', '--output', default=sys.stdout, dest='output',
                        type=argparse.FileType('w'),
                        help='Provide the url with the file to parse')
    args = parser.parse_args()

    cfile = args.text if args.text else urlopen(args.url, proxies=None)

    options = OptTable(parse_options(cfile.readlines()))
    print(getattr(options, args.format)(), file=args.output)
    args.output.close()
