# -*- coding: utf-8 -*-
#                     The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
""" This module is responsible to generate 'index.html' for the report.

The input for this step is the output directory, where individual reports
could be found. It parses those reports and generates 'index.html'. """

import re
import os
import os.path
import sys
import shutil
import itertools
import plistlib
import glob
import json
import logging
import datetime
from libscanbuild import duplicate_check
from libscanbuild.clang import get_version

__all__ = ['document']


def document(args):
    """ Generates cover report and returns the number of bugs/crashes. """

    html_reports_available = args.output_format in {'html', 'plist-html'}

    logging.debug('count crashes and bugs')
    crash_count = sum(1 for _ in read_crashes(args.output))
    bug_counter = create_counters()
    for bug in read_bugs(args.output, html_reports_available):
        bug_counter(bug)
    result = crash_count + bug_counter.total

    if html_reports_available and result:
        use_cdb = os.path.exists(args.cdb)

        logging.debug('generate index.html file')
        # common prefix for source files to have sorter path
        prefix = commonprefix_from(args.cdb) if use_cdb else os.getcwd()
        # assemble the cover from multiple fragments
        fragments = []
        try:
            if bug_counter.total:
                fragments.append(bug_summary(args.output, bug_counter))
                fragments.append(bug_report(args.output, prefix))
            if crash_count:
                fragments.append(crash_report(args.output, prefix))
            assemble_cover(args, prefix, fragments)
            # copy additional files to the report
            copy_resource_files(args.output)
            if use_cdb:
                shutil.copy(args.cdb, args.output)
        finally:
            for fragment in fragments:
                os.remove(fragment)
    return result


def assemble_cover(args, prefix, fragments):
    """ Put together the fragments into a final report. """

    import getpass
    import socket

    if args.html_title is None:
        args.html_title = os.path.basename(prefix) + ' - analyzer results'

    with open(os.path.join(args.output, 'index.html'), 'w') as handle:
        indent = 0
        handle.write(reindent("""
        |<!DOCTYPE html>
        |<html>
        |  <head>
        |    <title>{html_title}</title>
        |    <link type="text/css" rel="stylesheet" href="scanview.css"/>
        |    <script type='text/javascript' src="sorttable.js"></script>
        |    <script type='text/javascript' src='selectable.js'></script>
        |  </head>""", indent).format(html_title=args.html_title))
        handle.write(comment('SUMMARYENDHEAD'))
        handle.write(reindent("""
        |  <body>
        |    <h1>{html_title}</h1>
        |    <table>
        |      <tr><th>User:</th><td>{user_name}@{host_name}</td></tr>
        |      <tr><th>Working Directory:</th><td>{current_dir}</td></tr>
        |      <tr><th>Command Line:</th><td>{cmd_args}</td></tr>
        |      <tr><th>Clang Version:</th><td>{clang_version}</td></tr>
        |      <tr><th>Date:</th><td>{date}</td></tr>
        |    </table>""", indent).format(html_title=args.html_title,
                                         user_name=getpass.getuser(),
                                         host_name=socket.gethostname(),
                                         current_dir=prefix,
                                         cmd_args=' '.join(sys.argv),
                                         clang_version=get_version(args.clang),
                                         date=datetime.datetime.today(
                                         ).strftime('%c')))
        for fragment in fragments:
            # copy the content of fragments
            with open(fragment, 'r') as input_handle:
                shutil.copyfileobj(input_handle, handle)
        handle.write(reindent("""
        |  </body>
        |</html>""", indent))


def bug_summary(output_dir, bug_counter):
    """ Bug summary is a HTML table to give a better overview of the bugs. """

    name = os.path.join(output_dir, 'summary.html.fragment')
    with open(name, 'w') as handle:
        indent = 4
        handle.write(reindent("""
        |<h2>Bug Summary</h2>
        |<table>
        |  <thead>
        |    <tr>
        |      <td>Bug Type</td>
        |      <td>Quantity</td>
        |      <td class="sorttable_nosort">Display?</td>
        |    </tr>
        |  </thead>
        |  <tbody>""", indent))
        handle.write(reindent("""
        |    <tr style="font-weight:bold">
        |      <td class="SUMM_DESC">All Bugs</td>
        |      <td class="Q">{0}</td>
        |      <td>
        |        <center>
        |          <input checked type="checkbox" id="AllBugsCheck"
        |                 onClick="CopyCheckedStateToCheckButtons(this);"/>
        |        </center>
        |      </td>
        |    </tr>""", indent).format(bug_counter.total))
        for category, types in bug_counter.categories.items():
            handle.write(reindent("""
        |    <tr>
        |      <th>{0}</th><th colspan=2></th>
        |    </tr>""", indent).format(category))
            for bug_type in types.values():
                handle.write(reindent("""
        |    <tr>
        |      <td class="SUMM_DESC">{bug_type}</td>
        |      <td class="Q">{bug_count}</td>
        |      <td>
        |        <center>
        |          <input checked type="checkbox"
        |                 onClick="ToggleDisplay(this,'{bug_type_class}');"/>
        |        </center>
        |      </td>
        |    </tr>""", indent).format(**bug_type))
        handle.write(reindent("""
        |  </tbody>
        |</table>""", indent))
        handle.write(comment('SUMMARYBUGEND'))
    return name


def bug_report(output_dir, prefix):
    """ Creates a fragment from the analyzer reports. """

    pretty = prettify_bug(prefix, output_dir)
    bugs = (pretty(bug) for bug in read_bugs(output_dir, True))

    name = os.path.join(output_dir, 'bugs.html.fragment')
    with open(name, 'w') as handle:
        indent = 4
        handle.write(reindent("""
        |<h2>Reports</h2>
        |<table class="sortable" style="table-layout:automatic">
        |  <thead>
        |    <tr>
        |      <td>Bug Group</td>
        |      <td class="sorttable_sorted">
        |        Bug Type
        |        <span id="sorttable_sortfwdind">&nbsp;&#x25BE;</span>
        |      </td>
        |      <td>File</td>
        |      <td>Function/Method</td>
        |      <td class="Q">Line</td>
        |      <td class="Q">Path Length</td>
        |      <td class="sorttable_nosort"></td>
        |    </tr>
        |  </thead>
        |  <tbody>""", indent))
        handle.write(comment('REPORTBUGCOL'))
        for current in bugs:
            handle.write(reindent("""
        |    <tr class="{bug_type_class}">
        |      <td class="DESC">{bug_category}</td>
        |      <td class="DESC">{bug_type}</td>
        |      <td>{bug_file}</td>
        |      <td class="DESC">{bug_function}</td>
        |      <td class="Q">{bug_line}</td>
        |      <td class="Q">{bug_path_length}</td>
        |      <td><a href="{report_file}#EndPath">View Report</a></td>
        |    </tr>""", indent).format(**current))
            handle.write(comment('REPORTBUG', {'id': current['report_file']}))
        handle.write(reindent("""
        |  </tbody>
        |</table>""", indent))
        handle.write(comment('REPORTBUGEND'))
    return name


def crash_report(output_dir, prefix):
    """ Creates a fragment from the compiler crashes. """

    pretty = prettify_crash(prefix, output_dir)
    crashes = (pretty(crash) for crash in read_crashes(output_dir))

    name = os.path.join(output_dir, 'crashes.html.fragment')
    with open(name, 'w') as handle:
        indent = 4
        handle.write(reindent("""
        |<h2>Analyzer Failures</h2>
        |<p>The analyzer had problems processing the following files:</p>
        |<table>
        |  <thead>
        |    <tr>
        |      <td>Problem</td>
        |      <td>Source File</td>
        |      <td>Preprocessed File</td>
        |      <td>STDERR Output</td>
        |    </tr>
        |  </thead>
        |  <tbody>""", indent))
        for current in crashes:
            handle.write(reindent("""
        |    <tr>
        |      <td>{problem}</td>
        |      <td>{source}</td>
        |      <td><a href="{file}">preprocessor output</a></td>
        |      <td><a href="{stderr}">analyzer std err</a></td>
        |    </tr>""", indent).format(**current))
            handle.write(comment('REPORTPROBLEM', current))
        handle.write(reindent("""
        |  </tbody>
        |</table>""", indent))
        handle.write(comment('REPORTCRASHES'))
    return name


def read_crashes(output_dir):
    """ Generate a unique sequence of crashes from given output directory. """

    return (parse_crash(filename)
            for filename in glob.iglob(os.path.join(output_dir, 'failures',
                                                    '*.info.txt')))


def read_bugs(output_dir, html):
    """ Generate a unique sequence of bugs from given output directory.

    Duplicates can be in a project if the same module was compiled multiple
    times with different compiler options. These would be better to show in
    the final report (cover) only once. """

    parser = parse_bug_html if html else parse_bug_plist
    pattern = '*.html' if html else '*.plist'

    duplicate = duplicate_check(
        lambda bug: '{bug_line}.{bug_path_length}:{bug_file}'.format(**bug))

    bugs = itertools.chain.from_iterable(
        # parser creates a bug generator not the bug itself
        parser(filename)
        for filename in glob.iglob(os.path.join(output_dir, pattern)))

    return (bug for bug in bugs if not duplicate(bug))


def parse_bug_plist(filename):
    """ Returns the generator of bugs from a single .plist file. """

    content = plistlib.readPlist(filename)
    files = content.get('files')
    for bug in content.get('diagnostics', []):
        if len(files) <= int(bug['location']['file']):
            logging.warning('Parsing bug from "%s" failed', filename)
            continue

        yield {
            'result': filename,
            'bug_type': bug['type'],
            'bug_category': bug['category'],
            'bug_line': int(bug['location']['line']),
            'bug_path_length': int(bug['location']['col']),
            'bug_file': files[int(bug['location']['file'])]
        }


def parse_bug_html(filename):
    """ Parse out the bug information from HTML output. """

    patterns = [re.compile(r'<!-- BUGTYPE (?P<bug_type>.*) -->$'),
                re.compile(r'<!-- BUGFILE (?P<bug_file>.*) -->$'),
                re.compile(r'<!-- BUGPATHLENGTH (?P<bug_path_length>.*) -->$'),
                re.compile(r'<!-- BUGLINE (?P<bug_line>.*) -->$'),
                re.compile(r'<!-- BUGCATEGORY (?P<bug_category>.*) -->$'),
                re.compile(r'<!-- BUGDESC (?P<bug_description>.*) -->$'),
                re.compile(r'<!-- FUNCTIONNAME (?P<bug_function>.*) -->$')]
    endsign = re.compile(r'<!-- BUGMETAEND -->')

    bug = {
        'report_file': filename,
        'bug_function': 'n/a',  # compatibility with < clang-3.5
        'bug_category': 'Other',
        'bug_line': 0,
        'bug_path_length': 1
    }

    with open(filename) as handler:
        for line in handler.readlines():
            # do not read the file further
            if endsign.match(line):
                break
            # search for the right lines
            for regex in patterns:
                match = regex.match(line.strip())
                if match:
                    bug.update(match.groupdict())
                    break

    encode_value(bug, 'bug_line', int)
    encode_value(bug, 'bug_path_length', int)

    yield bug


def parse_crash(filename):
    """ Parse out the crash information from the report file. """

    match = re.match(r'(.*)\.info\.txt', filename)
    name = match.group(1) if match else None
    with open(filename, mode='rb') as handler:
        # this is a workaround to fix windows read '\r\n' as new lines.
        lines = [line.decode().rstrip() for line in handler.readlines()]
        return {
            'source': lines[0],
            'problem': lines[1],
            'file': name,
            'info': name + '.info.txt',
            'stderr': name + '.stderr.txt'
        }


def category_type_name(bug):
    """ Create a new bug attribute from bug by category and type.

    The result will be used as CSS class selector in the final report. """

    def smash(key):
        """ Make value ready to be HTML attribute value. """

        return bug.get(key, '').lower().replace(' ', '_').replace("'", '')

    return escape('bt_' + smash('bug_category') + '_' + smash('bug_type'))


def create_counters():
    """ Create counters for bug statistics.

    Two entries are maintained: 'total' is an integer, represents the
    number of bugs. The 'categories' is a two level categorisation of bug
    counters. The first level is 'bug category' the second is 'bug type'.
    Each entry in this classification is a dictionary of 'count', 'type'
    and 'label'. """

    def predicate(bug):
        bug_category = bug['bug_category']
        bug_type = bug['bug_type']
        current_category = predicate.categories.get(bug_category, dict())
        current_type = current_category.get(bug_type, {
            'bug_type': bug_type,
            'bug_type_class': category_type_name(bug),
            'bug_count': 0
        })
        current_type.update({'bug_count': current_type['bug_count'] + 1})
        current_category.update({bug_type: current_type})
        predicate.categories.update({bug_category: current_category})
        predicate.total += 1

    predicate.total = 0
    predicate.categories = dict()
    return predicate


def prettify_bug(prefix, output_dir):
    def predicate(bug):
        """ Make safe this values to embed into HTML. """

        bug['bug_type_class'] = category_type_name(bug)

        encode_value(bug, 'bug_file', lambda x: escape(chop(prefix, x)))
        encode_value(bug, 'bug_category', escape)
        encode_value(bug, 'bug_type', escape)
        encode_value(bug, 'report_file', lambda x: escape(chop(output_dir, x)))
        return bug

    return predicate


def prettify_crash(prefix, output_dir):
    def predicate(crash):
        """ Make safe this values to embed into HTML. """

        encode_value(crash, 'source', lambda x: escape(chop(prefix, x)))
        encode_value(crash, 'problem', escape)
        encode_value(crash, 'file', lambda x: escape(chop(output_dir, x)))
        encode_value(crash, 'info', lambda x: escape(chop(output_dir, x)))
        encode_value(crash, 'stderr', lambda x: escape(chop(output_dir, x)))
        return crash

    return predicate


def copy_resource_files(output_dir):
    """ Copy the javascript and css files to the report directory. """

    this_dir = os.path.dirname(os.path.realpath(__file__))
    for resource in os.listdir(os.path.join(this_dir, 'resources')):
        shutil.copy(os.path.join(this_dir, 'resources', resource), output_dir)


def encode_value(container, key, encode):
    """ Run 'encode' on 'container[key]' value and update it. """

    if key in container:
        value = encode(container[key])
        container.update({key: value})


def chop(prefix, filename):
    """ Create 'filename' from '/prefix/filename' """

    return filename if not len(prefix) else os.path.relpath(filename, prefix)


def escape(text):
    """ Paranoid HTML escape method. (Python version independent) """

    escape_table = {
        '&': '&amp;',
        '"': '&quot;',
        "'": '&apos;',
        '>': '&gt;',
        '<': '&lt;'
    }
    return ''.join(escape_table.get(c, c) for c in text)


def reindent(text, indent):
    """ Utility function to format html output and keep indentation. """

    result = ''
    for line in text.splitlines():
        if len(line.strip()):
            result += ' ' * indent + line.split('|')[1] + os.linesep
    return result


def comment(name, opts=dict()):
    """ Utility function to format meta information as comment. """

    attributes = ''
    for key, value in opts.items():
        attributes += ' {0}="{1}"'.format(key, value)

    return '<!-- {0}{1} -->{2}'.format(name, attributes, os.linesep)


def commonprefix_from(filename):
    """ Create file prefix from a compilation database entries. """

    with open(filename, 'r') as handle:
        return commonprefix(item['file'] for item in json.load(handle))


def commonprefix(files):
    """ Fixed version of os.path.commonprefix.

    :param files: list of file names.
    :return: the longest path prefix that is a prefix of all files. """
    result = None
    for current in files:
        if result is not None:
            result = os.path.commonprefix([result, current])
        else:
            result = current

    if result is None:
        return ''
    elif not os.path.isdir(result):
        return os.path.dirname(result)
    else:
        return os.path.abspath(result)
