#!/usr/bin/env python

import os
import argparse
import xml.etree.ElementTree as ET
from StringIO import StringIO
from collections import namedtuple
from docutils.core import publish_string


TEST_RESULT_FILE = '/tmp/tests-report-xivo-auto-%s.html'
path = '/data/test_results'

TEXT_HEADER = """
***************************
XiVO AUTOMATIC TEST REPORTS
***************************

This is a list of tests that are run daily by the `Continuous Integration system
<http://xivo.solutions>`_ of XiVO. The source code of the tests is available on
`Gitlab <http://gitlab.com/xivo.solutions/xivo-acceptance>`_.

The tests listed here were all passing at the moment of the release.

.. contents::


"""

Step = namedtuple("Step", ('feature', 'scenario', 'step'))


class Features(object):
    def __init__(self):
        self.steps = []

    def add_step(self, feature, scenario, step):
        self.steps.append(Step(feature, scenario, step))

    def names(self):
        return sorted(set(step.feature for step in self.steps))

    def scenarios(self, feature):
        result = {}
        scenarios = set(step.scenario for step in self.steps if step.feature == feature)
        for scenario in scenarios:
            result[scenario] = (step.step for step in self.steps if step.feature == feature and step.scenario == scenario)

        return result


def get_features(path):
    dirs = os.listdir(path)
    features = Features()
    for file in dirs:
        if file.endswith('xml'):
            xml_file_path = os.path.join(path, file)
            tree = ET.parse(xml_file_path)
            root = tree.getroot()

            for child in root:
                feature_name, scenario_title = child.attrib['classname'].split(':', 1)
                feature_name = feature_name.strip()
                scenario_title = scenario_title.strip()
                step_name = child.attrib['name']
                features.add_step(feature_name, scenario_title, step_name)
    return features


def format_features(features):
    fobj = StringIO()
    fobj.write(TEXT_HEADER)

    for feature_name in features.names():
        scenarios = features.scenarios(feature_name)
        fobj.write(_format_feature(feature_name, scenarios))

    result = fobj.getvalue()
    fobj.close()
    return result


def _format_feature(feature_name, scenarios):
    formatted_scenarios = [_format_scenario(scenario, steps) for scenario, steps in scenarios.iteritems()]
    feature_info = {'feature_name': feature_name,
                    'title_decoration': '=' * len(feature_name),
                    'scenarios': '\n'.join(formatted_scenarios)}
    return '\n\n%(feature_name)s\n%(title_decoration)s\n\n%(scenarios)s\n' % feature_info


def _format_scenario(scenario, steps):
    result = '* %s\n\n' % _escape_stars(scenario)
    result += '\n'.join('  * %s' % _escape_stars(step) for step in steps)
    return result


def _escape_stars(string_to_escape):
    return string_to_escape.replace('*', '\*')


def write_output_file(formatted_text, output_file):
    output_html = publish_string(formatted_text, writer_name='html')

    with open(output_file, 'w') as fobj:
        fobj.write(output_html)


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('version', help='Version to freeze')

    args = parser.parse_args()

    features = get_features(path)
    formatted_text = format_features(features)
    write_output_file(formatted_text, TEST_RESULT_FILE % args.version)
