# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.

import functools
import hashlib
import logging
import os
import re
import sys

try:
  import csscompressor
except ImportError:
  logging.critical('Cannot import the third-party Python package csscompressor')
  sys.exit(1)

try:
  import jsmin
except ImportError:
  logging.critical('Cannot import the third-party Python package jsmin')
  sys.exit(1)


class HtmlExport(object):
  """HTML exporter class for APM quality scores."""

  _NEW_LINE = '\n'

  # CSS and JS file paths.
  _PATH = os.path.dirname(os.path.realpath(__file__))
  _CSS_FILEPATH = os.path.join(_PATH, 'results.css')
  _CSS_MINIFIED = True
  _JS_FILEPATH = os.path.join(_PATH, 'results.js')
  _JS_MINIFIED = True

  def __init__(self, output_filepath):
    self._scores_data_frame = None
    self._output_filepath = output_filepath

  def Export(self, scores_data_frame):
    """Exports scores into an HTML file.

    Args:
      scores_data_frame: DataFrame instance.
    """
    self._scores_data_frame = scores_data_frame
    html = ['<html>',
            self._BuildHeader(),
            ('<script type="text/javascript">'
              '(function () {'
                'window.addEventListener(\'load\', function () {'
                  'var inspector = new AudioInspector();'
                '});'
             '})();'
             '</script>'),
            '<body>',
            self._BuildBody(),
            '</body>',
            '</html>']
    self._Save(self._output_filepath, self._NEW_LINE.join(html))

  def _BuildHeader(self):
    """Builds the <head> section of the HTML file.

    The header contains the page title and either embedded or linked CSS and JS
    files.

    Returns:
      A string with <head>...</head> HTML.
    """
    html = ['<head>', '<title>Results</title>']

    # Add Material Design hosted libs.
    html.append('<link rel="stylesheet" href="http://fonts.googleapis.com/'
                'css?family=Roboto:300,400,500,700" type="text/css">')
    html.append('<link rel="stylesheet" href="https://fonts.googleapis.com/'
                'icon?family=Material+Icons">')
    html.append('<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/'
                'material.indigo-pink.min.css">')
    html.append('<script defer src="https://code.getmdl.io/1.3.0/'
                'material.min.js"></script>')

    # Embed custom JavaScript and CSS files.
    html.append('<script>')
    with open(self._JS_FILEPATH) as f:
      html.append(jsmin.jsmin(f.read()) if self._JS_MINIFIED else (
          f.read().rstrip()))
    html.append('</script>')
    html.append('<style>')
    with open(self._CSS_FILEPATH) as f:
      html.append(csscompressor.compress(f.read()) if self._CSS_MINIFIED else (
          f.read().rstrip()))
    html.append('</style>')

    html.append('</head>')

    return self._NEW_LINE.join(html)

  def _BuildBody(self):
    """Builds the content of the <body> section."""
    score_names = self._scores_data_frame['eval_score_name'].drop_duplicates(
    ).values.tolist()

    html = [
        ('<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header '
         'mdl-layout--fixed-tabs">'),
        '<header class="mdl-layout__header">',
        '<div class="mdl-layout__header-row">',
        '<span class="mdl-layout-title">APM QA results ({})</span>'.format(
            self._output_filepath),
        '</div>',
    ]

    # Tab selectors.
    html.append('<div class="mdl-layout__tab-bar mdl-js-ripple-effect">')
    for tab_index, score_name in enumerate(score_names):
      is_active = tab_index == 0
      html.append('<a href="#score-tab-{}" class="mdl-layout__tab{}">'
                  '{}</a>'.format(tab_index,
                                  ' is-active' if is_active else '',
                                  self._FormatName(score_name)))
    html.append('</div>')

    html.append('</header>')
    html.append('<main class="mdl-layout__content" style="overflow-x: auto;">')

    # Tabs content.
    for tab_index, score_name in enumerate(score_names):
      html.append('<section class="mdl-layout__tab-panel{}" '
                  'id="score-tab-{}">'.format(
                      ' is-active' if is_active else '', tab_index))
      html.append('<div class="page-content">')
      html.append(self._BuildScoreTab(score_name, ('s{}'.format(tab_index),)))
      html.append('</div>')
      html.append('</section>')

    html.append('</main>')
    html.append('</div>')

    # Add snackbar for notifications.
    html.append(
        '<div id="snackbar" aria-live="assertive" aria-atomic="true"'
            ' aria-relevant="text" class="mdl-snackbar mdl-js-snackbar">'
          '<div class="mdl-snackbar__text"></div>'
          '<button type="button" class="mdl-snackbar__action"></button>'
        '</div>')

    return self._NEW_LINE.join(html)

  def _BuildScoreTab(self, score_name, anchor_data):
    """Builds the content of a tab."""
    # Find unique values.
    scores = self._scores_data_frame[
        self._scores_data_frame.eval_score_name == score_name]
    apm_configs = sorted(self._FindUniqueTuples(scores, ['apm_config']))
    test_data_gen_configs = sorted(self._FindUniqueTuples(
        scores, ['test_data_gen', 'test_data_gen_params']))

    html = [
        '<div class="mdl-grid">',
        '<div class="mdl-layout-spacer"></div>',
        '<div class="mdl-cell mdl-cell--10-col">',
        ('<table class="mdl-data-table mdl-js-data-table mdl-shadow--2dp" '
         'style="width: 100%;">'),
    ]

    # Header.
    html.append('<thead><tr><th>APM config / Test data generator</th>')
    for test_data_gen_info in test_data_gen_configs:
      html.append('<th>{} {}</th>'.format(
          self._FormatName(test_data_gen_info[0]), test_data_gen_info[1]))
    html.append('</tr></thead>')

    # Body.
    html.append('<tbody>')
    for apm_config in apm_configs:
      html.append('<tr><td>' + self._FormatName(apm_config[0]) + '</td>')
      for test_data_gen_info in test_data_gen_configs:
        dialog_id = self._ScoreStatsInspectorDialogId(
            score_name, apm_config[0], test_data_gen_info[0],
            test_data_gen_info[1])
        html.append(
            '<td onclick="openScoreStatsInspector(\'{}\')">{}</td>'.format(
                dialog_id, self._BuildScoreTableCell(
                    score_name, test_data_gen_info[0], test_data_gen_info[1],
                    apm_config[0])))
      html.append('</tr>')
    html.append('</tbody>')

    html.append('</table></div><div class="mdl-layout-spacer"></div></div>')

    html.append(self._BuildScoreStatsInspectorDialogs(
        score_name, apm_configs, test_data_gen_configs,
        anchor_data))

    return self._NEW_LINE.join(html)

  def _BuildScoreTableCell(self, score_name, test_data_gen,
                           test_data_gen_params, apm_config):
    """Builds the content of a table cell for a score table."""
    scores = self._SliceDataForScoreTableCell(
        score_name, apm_config, test_data_gen, test_data_gen_params)
    stats = self._ComputeScoreStats(scores)

    html = []
    items_id_prefix = (
        score_name + test_data_gen + test_data_gen_params + apm_config)
    if stats['count'] == 1:
      # Show the only available score.
      item_id = hashlib.md5(items_id_prefix.encode('utf-8')).hexdigest()
      html.append('<div id="single-value-{0}">{1:f}</div>'.format(
          item_id, scores['score'].mean()))
      html.append('<div class="mdl-tooltip" data-mdl-for="single-value-{}">{}'
          '</div>'.format(item_id, 'single value'))
    else:
      # Show stats.
      for stat_name in ['min', 'max', 'mean', 'std dev']:
        item_id = hashlib.md5(
            (items_id_prefix + stat_name).encode('utf-8')).hexdigest()
        html.append('<div id="stats-{0}">{1:f}</div>'.format(
            item_id, stats[stat_name]))
        html.append('<div class="mdl-tooltip" data-mdl-for="stats-{}">{}'
            '</div>'.format(item_id, stat_name))

    return self._NEW_LINE.join(html)

  def _BuildScoreStatsInspectorDialogs(
      self, score_name, apm_configs, test_data_gen_configs, anchor_data):
    """Builds a set of score stats inspector dialogs."""
    html = []
    for apm_config in apm_configs:
      for test_data_gen_info in test_data_gen_configs:
        dialog_id = self._ScoreStatsInspectorDialogId(
            score_name, apm_config[0],
            test_data_gen_info[0], test_data_gen_info[1])

        html.append('<dialog class="mdl-dialog" id="{}" '
                    'style="width: 40%;">'.format(dialog_id))

        # Content.
        html.append('<div class="mdl-dialog__content">')
        html.append('<h6><strong>APM config preset</strong>: {}<br/>'
                    '<strong>Test data generator</strong>: {} ({})</h6>'.format(
                        self._FormatName(apm_config[0]),
                        self._FormatName(test_data_gen_info[0]),
                        test_data_gen_info[1]))
        html.append(self._BuildScoreStatsInspectorDialog(
            score_name, apm_config[0], test_data_gen_info[0],
            test_data_gen_info[1], anchor_data + (dialog_id,)))
        html.append('</div>')

        # Actions.
        html.append('<div class="mdl-dialog__actions">')
        html.append('<button type="button" class="mdl-button" '
                    'onclick="closeScoreStatsInspector()">'
                    'Close</button>')
        html.append('</div>')

        html.append('</dialog>')

    return self._NEW_LINE.join(html)

  def _BuildScoreStatsInspectorDialog(
      self, score_name, apm_config, test_data_gen, test_data_gen_params,
      anchor_data):
    """Builds one score stats inspector dialog."""
    scores = self._SliceDataForScoreTableCell(
        score_name, apm_config, test_data_gen, test_data_gen_params)

    capture_render_pairs = sorted(self._FindUniqueTuples(
        scores, ['capture', 'render']))
    echo_simulators = sorted(self._FindUniqueTuples(scores, ['echo_simulator']))

    html = ['<table class="mdl-data-table mdl-js-data-table mdl-shadow--2dp">']

    # Header.
    html.append('<thead><tr><th>Capture-Render / Echo simulator</th>')
    for echo_simulator in echo_simulators:
      html.append('<th>' + self._FormatName(echo_simulator[0]) +'</th>')
    html.append('</tr></thead>')

    # Body.
    html.append('<tbody>')
    for row, (capture, render) in enumerate(capture_render_pairs):
      html.append('<tr><td><div>{}</div><div>{}</div></td>'.format(
          capture, render))
      for col, echo_simulator in enumerate(echo_simulators):
        score_tuple = self._SliceDataForScoreStatsTableCell(
            scores, capture, render, echo_simulator[0])
        cell_class = 'r{}c{}'.format(row, col)
        html.append('<td class="single-score-cell {}">{}</td>'.format(
            cell_class, self._BuildScoreStatsInspectorTableCell(
                score_tuple, anchor_data + (cell_class,))))
      html.append('</tr>')
    html.append('</tbody>')

    html.append('</table>')

    # Placeholder for the audio inspector.
    html.append('<div class="audio-inspector-placeholder"></div>')

    return self._NEW_LINE.join(html)

  def _BuildScoreStatsInspectorTableCell(self, score_tuple, anchor_data):
    """Builds the content of a cell of a score stats inspector."""
    anchor = '&'.join(anchor_data)
    html = [('<div class="v">{}</div>'
             '<button class="mdl-button mdl-js-button mdl-button--icon"'
                    ' data-anchor="{}">'
               '<i class="material-icons mdl-color-text--blue-grey">link</i>'
             '</button>').format(score_tuple.score, anchor)]

    # Add all the available file paths as hidden data.
    for field_name in score_tuple.keys():
      if field_name.endswith('_filepath'):
        html.append('<input type="hidden" name="{}" value="{}">'.format(
            field_name, score_tuple[field_name]))

    return self._NEW_LINE.join(html)

  def _SliceDataForScoreTableCell(
      self, score_name, apm_config, test_data_gen, test_data_gen_params):
    """Slices |self._scores_data_frame| to extract the data for a tab."""
    masks = []
    masks.append(self._scores_data_frame.eval_score_name == score_name)
    masks.append(self._scores_data_frame.apm_config == apm_config)
    masks.append(self._scores_data_frame.test_data_gen == test_data_gen)
    masks.append(
        self._scores_data_frame.test_data_gen_params == test_data_gen_params)
    mask = functools.reduce((lambda i1, i2: i1 & i2), masks)
    del masks
    return self._scores_data_frame[mask]

  @classmethod
  def _SliceDataForScoreStatsTableCell(
      cls, scores, capture, render, echo_simulator):
    """Slices |scores| to extract the data for a tab."""
    masks = []

    masks.append(scores.capture == capture)
    masks.append(scores.render == render)
    masks.append(scores.echo_simulator == echo_simulator)
    mask = functools.reduce((lambda i1, i2: i1 & i2), masks)
    del masks

    sliced_data = scores[mask]
    assert len(sliced_data) == 1, 'single score is expected'
    return sliced_data.iloc[0]

  @classmethod
  def _FindUniqueTuples(cls, data_frame, fields):
    """Slices |data_frame| to a list of fields and finds unique tuples."""
    return data_frame[fields].drop_duplicates().values.tolist()

  @classmethod
  def _ComputeScoreStats(cls, data_frame):
    """Computes score stats."""
    scores = data_frame['score']
    return {
        'count': scores.count(),
        'min': scores.min(),
        'max': scores.max(),
        'mean': scores.mean(),
        'std dev': scores.std(),
    }

  @classmethod
  def _ScoreStatsInspectorDialogId(cls, score_name, apm_config, test_data_gen,
                                   test_data_gen_params):
    """Assigns a unique name to a dialog."""
    return 'score-stats-dialog-' + hashlib.md5(
        'score-stats-inspector-{}-{}-{}-{}'.format(
            score_name, apm_config, test_data_gen,
            test_data_gen_params).encode('utf-8')).hexdigest()

  @classmethod
  def _Save(cls, output_filepath, html):
    """Writes the HTML file.

    Args:
      output_filepath: output file path.
      html: string with the HTML content.
    """
    with open(output_filepath, 'w') as f:
      f.write(html)

  @classmethod
  def _FormatName(cls, name):
    """Formats a name.

    Args:
      name: a string.

    Returns:
      A copy of name in which underscores and dashes are replaced with a space.
    """
    return re.sub(r'[_\-]', ' ', name)
