# Copyright 2015 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Generate XML and HTML test reports."""

from __future__ import print_function

try:
    from mako.runtime import Context
    from mako.template import Template
    from mako import exceptions
except (ImportError):
    pass  # Mako not installed but it is ok.
import datetime
import os
import string
import xml.etree.cElementTree as ET
import six


def _filter_msg(msg, output_format):
    """Filters out nonprintable and illegal characters from the message."""
    if output_format in ['XML', 'HTML']:
        # keep whitespaces but remove formfeed and vertical tab characters
        # that make XML report unparseable.
        filtered_msg = filter(
            lambda x: x in string.printable and x != '\f' and x != '\v',
            msg.decode('UTF-8', 'ignore'))
        if output_format == 'HTML':
            filtered_msg = filtered_msg.replace('"', '&quot;')
        return filtered_msg
    else:
        return msg


def new_junit_xml_tree():
    return ET.ElementTree(ET.Element('testsuites'))


def render_junit_xml_report(resultset,
                            report_file,
                            suite_package='grpc',
                            suite_name='tests'):
    """Generate JUnit-like XML report."""
    tree = new_junit_xml_tree()
    append_junit_xml_results(tree, resultset, suite_package, suite_name, '1')
    create_xml_report_file(tree, report_file)


def create_xml_report_file(tree, report_file):
    """Generate JUnit-like report file from xml tree ."""
    # ensure the report directory exists
    report_dir = os.path.dirname(os.path.abspath(report_file))
    if not os.path.exists(report_dir):
        os.makedirs(report_dir)
    tree.write(report_file, encoding='UTF-8')


def append_junit_xml_results(tree, resultset, suite_package, suite_name, id):
    """Append a JUnit-like XML report tree with test results as a new suite."""
    testsuite = ET.SubElement(
        tree.getroot(),
        'testsuite',
        id=id,
        package=suite_package,
        name=suite_name,
        timestamp=datetime.datetime.now().isoformat())
    failure_count = 0
    error_count = 0
    for shortname, results in six.iteritems(resultset):
        for result in results:
            xml_test = ET.SubElement(testsuite, 'testcase', name=shortname)
            if result.elapsed_time:
                xml_test.set('time', str(result.elapsed_time))
            filtered_msg = _filter_msg(result.message, 'XML')
            if result.state == 'FAILED':
                ET.SubElement(
                    xml_test, 'failure', message='Failure').text = filtered_msg
                failure_count += 1
            elif result.state == 'TIMEOUT':
                ET.SubElement(
                    xml_test, 'error', message='Timeout').text = filtered_msg
                error_count += 1
            elif result.state == 'SKIPPED':
                ET.SubElement(xml_test, 'skipped', message='Skipped')
    testsuite.set('failures', str(failure_count))
    testsuite.set('errors', str(error_count))


def render_interop_html_report(client_langs, server_langs, test_cases,
                               auth_test_cases, http2_cases, http2_server_cases,
                               resultset, num_failures, cloud_to_prod,
                               prod_servers, http2_interop):
    """Generate HTML report for interop tests."""
    template_file = 'tools/run_tests/interop/interop_html_report.template'
    try:
        mytemplate = Template(filename=template_file, format_exceptions=True)
    except NameError:
        print(
            'Mako template is not installed. Skipping HTML report generation.')
        return
    except IOError as e:
        print('Failed to find the template %s: %s' % (template_file, e))
        return

    sorted_test_cases = sorted(test_cases)
    sorted_auth_test_cases = sorted(auth_test_cases)
    sorted_http2_cases = sorted(http2_cases)
    sorted_http2_server_cases = sorted(http2_server_cases)
    sorted_client_langs = sorted(client_langs)
    sorted_server_langs = sorted(server_langs)
    sorted_prod_servers = sorted(prod_servers)

    args = {
        'client_langs': sorted_client_langs,
        'server_langs': sorted_server_langs,
        'test_cases': sorted_test_cases,
        'auth_test_cases': sorted_auth_test_cases,
        'http2_cases': sorted_http2_cases,
        'http2_server_cases': sorted_http2_server_cases,
        'resultset': resultset,
        'num_failures': num_failures,
        'cloud_to_prod': cloud_to_prod,
        'prod_servers': sorted_prod_servers,
        'http2_interop': http2_interop
    }

    html_report_out_dir = 'reports'
    if not os.path.exists(html_report_out_dir):
        os.mkdir(html_report_out_dir)
    html_file_path = os.path.join(html_report_out_dir, 'index.html')
    try:
        with open(html_file_path, 'w') as output_file:
            mytemplate.render_context(Context(output_file, **args))
    except:
        print(exceptions.text_error_template().render())
        raise


def render_perf_profiling_results(output_filepath, profile_names):
    with open(output_filepath, 'w') as output_file:
        output_file.write('<ul>\n')
        for name in profile_names:
            output_file.write('<li><a href=%s>%s</a></li>\n' % (name, name))
        output_file.write('</ul>\n')
