// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:math' as math;

import '../log/log.dart';
import '../server.dart';
import 'page_writer.dart';

/**
 * A page writer that will produce the page containing access to the full
 * content of the log.
 */
class LogPage extends PageWriter {
  /**
   * The instrumentation log to be written.
   */
  InstrumentationLog log;

  /**
   * The id of the entry groups to be displayed.
   */
  EntryGroup selectedGroup;

  /**
   * The entries in the selected group.
   */
  List<LogEntry> entries;

  /**
   * The index of the first entry to be written.
   */
  int pageStart = 0;

  /**
   * The number of entries to be written, or `null` if all of the entries should
   * be written.
   */
  int pageLength = null;

  /**
   * The number of digits in the event stamps that are the same for every entry.
   */
  int prefixLength;

  /**
   * A table mapping the ids of plugins to an index for the plugin.
   */
  Map<String, int> pluginIdMap = <String, int>{};

  /**
   * Initialize a newly created writer to write the content of the given
   * [instrumentationLog].
   */
  LogPage(this.log);

  /**
   * Return the encoding for the given [pluginId] that is used to build anchors.
   */
  int getPluginId(String pluginId) {
    return pluginIdMap.putIfAbsent(pluginId, () => pluginIdMap.length);
  }

  @override
  void writeBody(StringSink sink) {
    entries = log.entriesInGroup(selectedGroup);
    prefixLength = computePrefixLength(entries);

    writeMenu(sink);
    writeTwoColumns(
        sink, 'leftColumn', _writeLeftColumn, 'rightColumn', _writeRightColumn);
  }

  @override
  void writeScripts(StringSink sink) {
    super.writeScripts(sink);
    sink.writeln(r'''
var highlightedRows = [];
function clearHighlight() {
  for (i = 0; i < highlightedRows.length; i++) {
    setFontWeight(highlightedRows[i], "normal");
  }
}
function highlight(requestId, responseId) {
  clearHighlight();
  setFontWeight(requestId, "bold");
  setFontWeight(responseId, "bold");
  highlightedRows = [requestId, responseId];
}
function setFontWeight(id, weight) {
  var element = document.getElementById(id);
  if (element != null) {
    element.style.fontWeight = weight;
  }
}
function setDetails(detailsContent) {
  var element = document.getElementById("details");
  if (element != null) {
    element.innerHTML = detailsContent;
  }
}
function selectEntryGroup(pageStart) {
  var element = document.getElementById("entryGroup");
  var url = "/log?group=" + element.value;
  window.location.assign(url);
}
''');
  }

  /**
   * Write the content of the style sheet (without the 'script' tag) for the
   * page to the given [sink].
   */
  void writeStyleSheet(StringSink sink) {
    super.writeStyleSheet(sink);
    writeTwoColumnStyles(sink, 'leftColumn', 'rightColumn');
  }

  /**
   * Return the number of milliseconds elapsed between the [startEntry] and the
   * [endEntry], or a question .
   */
  String _getDuration(LogEntry startEntry, LogEntry endEntry) {
    if (startEntry != null && endEntry != null) {
      return (endEntry.timeStamp - startEntry.timeStamp).toString();
    }
    return '?';
  }

  /**
   * Write the given log [entry] to the given [sink].
   */
  void _writeEntry(StringSink sink, LogEntry entry) {
    String id = null;
    String clickHandler = 'clearHighlight()';
    String icon = '';
    String description = entry.kindName;
    if (entry is RequestEntry) {
      String entryId = entry.id;
      id = 'req$entryId';
      clickHandler = 'highlight(\'req$entryId\', \'res$entryId\')';
      icon = '&rarr;';
      description = entry.method;
    } else if (entry is ResponseEntry) {
      String entryId = entry.id;
      RequestEntry request = log.requestFor(entry);
      id = 'res$entryId';
      clickHandler = 'highlight(\'req$entryId\', \'res$entryId\')';
      icon = '&larr;';
      if (request != null) {
        int latency = entry.timeStamp - request.timeStamp;
        description =
            '${request.method} <span class="gray">($latency ms)</span>';
      }
    } else if (entry is NotificationEntry) {
      id = 'e${entry.index}';
      LogEntry pairedEntry = log.pairedEntry(entry);
      if (pairedEntry != null) {
        String pairedId = 'e${pairedEntry.index}';
        clickHandler = 'highlight(\'$id\', \'$pairedId\')';
      }
      icon = '&larr;';
      description = entry.event;
      if (entry.isServerStatus) {
        var analysisStatus = entry.param('analysis');
        if (analysisStatus is Map) {
          if (analysisStatus['isAnalyzing']) {
            description =
                '$description <span class="gray">(analysis)</span> (<a href="${WebServer.taskPath}?analysisStart=${entry.index}">tasks</a>)';
          } else {
            String duration = _getDuration(pairedEntry, entry);
            description =
                '$description <span class="gray">(analysis - $duration ms)</span>';
          }
        }
        var pubStatus = entry.param('pub');
        if (pubStatus is Map) {
          if (pubStatus['isListingPackageDirs']) {
            description = '$description <span class="gray">(pub)</span>';
          } else {
            String duration = _getDuration(pairedEntry, entry);
            description =
                '$description <span class="gray">(pub - $duration ms)</span>';
          }
        }
      }
    } else if (entry is PluginRequestEntry) {
      String entryId = entry.id;
      int pluginId = getPluginId(entry.pluginId);
      id = 'req$pluginId.$entryId';
      clickHandler =
          'highlight(\'req$pluginId.$entryId\', \'res$pluginId.$entryId\')';
      icon = '&rarr;';
      description = '${entry.method} (${entry.shortPluginId})';
    } else if (entry is PluginResponseEntry) {
      String entryId = entry.id;
      int pluginId = getPluginId(entry.pluginId);
      PluginRequestEntry request = log.pluginRequestFor(entry);
      id = 'res$pluginId.$entryId';
      clickHandler =
          'highlight(\'req$pluginId.$entryId\', \'res$pluginId.$entryId\')';
      icon = '&larr;';
      if (request != null) {
        int latency = entry.timeStamp - request.timeStamp;
        description =
            '${request.method} <span class="gray">($latency ms)</span> (${entry.shortPluginId})';
      }
    } else if (entry is PluginNotificationEntry) {
      id = 'e${entry.index}';
      LogEntry pairedEntry = log.pairedEntry(entry);
      if (pairedEntry != null) {
        String pairedId = 'e${pairedEntry.index}';
        clickHandler = 'highlight(\'$id\', \'$pairedId\')';
      }
      icon = '&larr;';
      description = '${entry.event} (${entry.shortPluginId})';
    } else if (entry is TaskEntry) {
      description = entry.description;
    } else if (entry is ErrorEntry) {
      description = '<span class="error">$description</span>';
    } else if (entry is PluginErrorEntry) {
      description =
          '<span class="error">$description</span> (${entry.shortPluginId})';
    } else if (entry is ExceptionEntry) {
      description = '<span class="error">$description</span>';
    } else if (entry is MalformedLogEntry) {
      description = '<span class="error">$description</span>';
    }
    id = id == null ? '' : 'id="$id" ';
    clickHandler = '$clickHandler; setDetails(\'${escape(entry.details())}\')';
    String timeStamp = entry.timeStamp.toString();
    if (prefixLength > 0) {
      timeStamp = timeStamp.substring(prefixLength);
    }

    sink.writeln('<tr ${id}onclick="$clickHandler">');
    sink.writeln('<td>$icon</td>');
    sink.writeln('<td>');
    sink.writeln(timeStamp);
    sink.writeln('</td>');
    sink.writeln('<td style="white-space:nowrap;">');
    sink.writeln(description);
    sink.writeln('</td>');
    sink.writeln('</tr>');
  }

  /**
   * Write the entries in the instrumentation log to the given [sink].
   */
  void _writeLeftColumn(StringSink sink) {
    int length = entries.length;
    int pageEnd =
        pageLength == null ? length : math.min(pageStart + pageLength, length);
    //
    // Write the header of the column.
    //
    sink.writeln('<div class="columnHeader">');
    sink.writeln('<div style="float: left">');
    sink.writeln('<select id="entryGroup" onchange="selectEntryGroup()">');
    for (EntryGroup group in EntryGroup.groups) {
      sink.write('<option value="');
      sink.write(group.id);
      sink.write('"');
      if (group == selectedGroup) {
        sink.write(' selected');
      }
      sink.write('>');
      sink.write(group.name);
      sink.writeln('</option>');
    }
    sink.writeln('</select>');
    if (length == 0) {
      sink.writeln('No matching events');
    } else {
      sink.writeln('Events $pageStart - ${pageEnd - 1} of $length');
    }
    sink.writeln('</div>');

    sink.writeln('<div style="float: right">');
    if (pageStart == 0) {
      sink.writeln('<button type="button" disabled><b>&lt;</b></button>');
    } else {
      sink.write('<button type="button">');
      sink.write(
          '<a href="${WebServer.logPath}?group=${selectedGroup.id}&start=${pageStart - pageLength}">');
      sink.write('<b>&lt;</b>');
      sink.writeln('</a></button>');
    }
    // TODO(brianwilkerson) Add a text field for selecting the start index.
    if (pageEnd == length) {
      sink.writeln('<button type="button" disabled><b>&gt;</b></button>');
    } else {
      sink.write('<button type="button">');
      sink.write(
          '<a href="${WebServer.logPath}?group=${selectedGroup.id}&start=${pageStart + pageLength}">');
      sink.write('<b>&gt;</b>');
      sink.writeln('</a></button>');
    }
    sink.writeln('</div>');
    sink.writeln('</div>');
    //
    // Write the main body of the column.
    //
    sink.writeln('<table class="fullWidth">');
    sink.writeln('<tr>');
    sink.writeln('<th class="narrow"></th>');
    sink.writeln('<th>Time</th>');
    sink.writeln('<th>Kind</th>');
    sink.writeln('</tr>');
    for (int i = pageStart; i < pageEnd; i++) {
      LogEntry entry = entries[i];
      _writeEntry(sink, entry);
    }
    sink.writeln('</table>');
  }

  /**
   * Write a placeholder to the given [sink] where the details of a selected
   * entry can be displayed.
   */
  void _writeRightColumn(StringSink sink) {
    //
    // Write the header of the column.
    //
    sink.writeln('<div class="columnHeader">');
    sink.writeln('<p><b>Entry Details</b></p>');
    sink.writeln('</div>');
    sink.writeln('<div id="details"></div>');
  }
}
