// 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.

/**
 * A representation of the contents of an instrumentation log.
 */
import 'dart:convert';
import 'dart:math' as math;

import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:path/path.dart' as path;

/**
 * A boolean-valued function of one argument.
 */
typedef bool Predicate<T>(T value);

/**
 * A description of a group of log entries.
 */
class EntryGroup {
  /**
   * A list of all of the instances of this class.
   */
  static final List<EntryGroup> groups = <EntryGroup>[
    new EntryGroup._(
        'nonTask', 'Non-task', (LogEntry entry) => entry is! TaskEntry),
    new EntryGroup._(
        'errors',
        'Errors',
        (LogEntry entry) =>
            entry is ErrorEntry ||
            entry is ExceptionEntry ||
            (entry is NotificationEntry && entry.isServerError)),
    new EntryGroup._('malformed', 'Malformed',
        (LogEntry entry) => entry is MalformedLogEntry),
    new EntryGroup._('all', 'All', (LogEntry entry) => true),
  ];

  /**
   * The unique id of the group.
   */
  final String id;

  /**
   * The human-readable name of the group.
   */
  final String name;

  /**
   * The filter used to determine which entries belong to the group. The filter
   * should return `true` for members and `false` for non-members.
   */
  final Predicate<LogEntry> filter;

  /**
   * Initialize a newly created entry group with the given state.
   */
  EntryGroup._(this.id, this.name, this.filter);

  /**
   * Given a list of [entries], return all of the entries in the list that are
   * members of this group.
   */
  List<LogEntry> computeMembers(List<LogEntry> entries) {
    return entries.where(filter).toList();
  }

  /**
   * Return the entry group with the given [id], or `null` if there is no group
   * with the given id.
   */
  static EntryGroup withId(String id) {
    for (EntryGroup group in groups) {
      if (group.id == id) {
        return group;
      }
    }
    return null;
  }
}

/**
 * A range of log entries, represented by the index of the first and last
 * entries in the range.
 */
class EntryRange {
  /**
   * The index of the first entry in the range.
   */
  int firstIndex;

  /**
   * The index of the first entry in the range.
   */
  int lastIndex;

  /**
   * Initialize a newly created range to represent the entries between the
   * [firstIndex] and the [lastIndex], inclusive.
   */
  EntryRange(this.firstIndex, this.lastIndex);
}

/**
 * A log entry representing an Err entry.
 */
class ErrorEntry extends GenericEntry {
  /**
   * Initialize a newly created log entry.
   */
  ErrorEntry(
      int index, int timeStamp, String entryKind, List<String> components)
      : super(index, timeStamp, entryKind, components);
}

/**
 * A log entry representing an Ex entry.
 */
class ExceptionEntry extends GenericEntry {
  /**
   * Initialize a newly created log entry.
   */
  ExceptionEntry(
      int index, int timeStamp, String entryKind, List<String> components)
      : super(index, timeStamp, entryKind, components);
}

/**
 * A representation of a generic log entry.
 */
class GenericEntry extends LogEntry {
  /**
   * The kind of the log entry.
   */
  String entryKind;

  /**
   * The components in the entry that follow the time stamp and entry kind.
   */
  List<String> components;

  /**
   * Initialize a newly created generic log entry to have the given [timeStamp],
   * [entryKind] and list of [components]
   */
  GenericEntry(int index, int timeStamp, this.entryKind, this.components)
      : super(index, timeStamp);

  @override
  String get kind => entryKind;

  @override
  void _appendDetails(StringBuffer buffer) {
    super._appendDetails(buffer);
    for (String component in components) {
      buffer.write(component);
      buffer.write('<br>');
    }
  }
}

/**
 * A log entry representing an PluginErr entry.
 */
class GenericPluginEntry extends GenericEntry with PluginEntryMixin {
  /**
   * The components describing the plugin associated with this entry.
   */
  final List<String> pluginData;

  /**
   * Initialize a newly created log entry.
   */
  GenericPluginEntry(int index, int timeStamp, String entryKind,
      List<String> components, this.pluginData)
      : super(index, timeStamp, entryKind, components);
}

/**
 * A representation of an instrumentation log.
 */
class InstrumentationLog {
  /**
   * The paths of the log files containing the entries.
   */
  List<String> logFilePaths;

  /**
   * The entries in the instrumentation log.
   */
  List<LogEntry> logEntries;

  /**
   * A table mapping the entry groups that have been computed to the list of
   * entries in that group.
   */
  Map<EntryGroup, List<LogEntry>> entryGroups = <EntryGroup, List<LogEntry>>{};

  /**
   * A table mapping entries that are paired with another entry to the entry
   * with which they are paired.
   */
  Map<LogEntry, LogEntry> _pairedEntries = <LogEntry, LogEntry>{};

  /**
   * A table mapping the id's of requests to the entry representing the request.
   */
  Map<String, RequestEntry> _requestMap = <String, RequestEntry>{};

  /**
   * A table mapping the id's of plugin requests to the entry representing the
   * request.
   */
  Map<String, PluginRequestEntry> _pluginRequestMap =
      <String, PluginRequestEntry>{};

  /**
   * A table mapping the id's of responses to the entry representing the
   * response.
   */
  Map<String, ResponseEntry> _responseMap = <String, ResponseEntry>{};

  /**
   * A table mapping the id's of plugin responses to the entry representing the
   * response.
   */
  Map<String, PluginResponseEntry> _pluginResponseMap =
      <String, PluginResponseEntry>{};

  /**
   * A table mapping the ids of completion events to the events with those ids.
   */
  Map<String, List<NotificationEntry>> _completionMap =
      <String, List<NotificationEntry>>{};

  /**
   * The ranges of entries that are between analysis start and analysis end
   * notifications.
   */
  List<EntryRange> analysisRanges;

  /**
   * Initialize a newly created instrumentation log by parsing each of the lines
   * in the [logContent] into a separate entry. The log contents should be the
   * contents of the files whose paths are in the given list of [logFilePaths].
   */
  InstrumentationLog(this.logFilePaths, List<String> logContent) {
    _parseLogContent(logContent);
  }

  /**
   * Return a list of the completion events associated with the given [id].
   */
  List<NotificationEntry> completionEventsWithId(String id) =>
      _completionMap[id];

  /**
   * Return the log entries that are contained in the given [group].
   */
  List<LogEntry> entriesInGroup(EntryGroup group) =>
      entryGroups.putIfAbsent(group, () => group.computeMembers(logEntries));

  /**
   * Return the entry that is paired with the given [entry], or `null` if there
   * is no entry paired with it.
   */
  LogEntry pairedEntry(LogEntry entry) => _pairedEntries[entry];

  /**
   * Return the response that corresponds to the given plugin request.
   */
  PluginRequestEntry pluginRequestFor(PluginResponseEntry entry) =>
      _pluginRequestMap[entry.id];

  /**
   * Return the response that corresponds to the given request.
   */
  PluginResponseEntry pluginResponseFor(PluginRequestEntry entry) =>
      _pluginResponseMap[entry.id];

  /**
   * Return the response that corresponds to the given request.
   */
  RequestEntry requestFor(ResponseEntry entry) => _requestMap[entry.id];

  /**
   * Return the response that corresponds to the given request.
   */
  ResponseEntry responseFor(RequestEntry entry) => _responseMap[entry.id];

  /**
   * Return a list containing all of the task entries between the start of
   * analysis notification at the given [startIndex] and the matching end of
   * analysis notification (or the end of the log if the log does not contain a
   * corresponding end notification.
   */
  List<TaskEntry> taskEntriesFor(int startIndex) {
    List<TaskEntry> taskEntries = <TaskEntry>[];
    NotificationEntry startEntry = logEntries[startIndex];
    LogEntry endEntry = pairedEntry(startEntry);
    int lastIndex = endEntry == null ? logEntries.length : endEntry.index;
    for (int i = startEntry.index + 1; i < lastIndex; i++) {
      LogEntry entry = logEntries[i];
      if (entry is TaskEntry) {
        taskEntries.add(entry);
      }
    }
    return taskEntries;
  }

  /**
   * Return `true` if the given [logContent] appears to be from session data.
   */
  bool _isSessionData(List<String> logContent) {
    if (logContent.length < 2) {
      return false;
    }
    String firstLine = logContent[0];
    return firstLine.startsWith('-----') && logContent[1].startsWith('~') ||
        firstLine.startsWith('~');
  }

  /**
   * Merge any multi-line entries into a single line so that every element in
   * the given [logContent] is a single entry.
   */
  void _mergeEntries(List<String> logContent) {
    bool isStartOfEntry(String line) {
      return line.startsWith(LogEntry.entryRegExp);
    }

    String merge(String line, List<String> extraLines) {
      StringBuffer buffer = new StringBuffer();
      buffer.writeln(line);
      for (String extraLine in extraLines) {
        buffer.writeln(extraLine);
      }
      return buffer.toString();
    }

    List<String> extraLines = <String>[];
    for (int i = logContent.length - 1; i >= 0; i--) {
      String line = logContent[i];
      if (isStartOfEntry(line)) {
        if (extraLines.isNotEmpty) {
          logContent[i] = merge(line, extraLines);
        }
        extraLines.clear();
      } else {
        logContent.removeAt(i);
        extraLines.insert(0, line);
      }
    }
    if (extraLines.isNotEmpty) {
      int count = math.min(extraLines.length, 10);
      StringBuffer buffer = new StringBuffer();
      buffer.writeln('${extraLines.length} non-entry lines before any entry');
      buffer.writeln('First $count lines:');
      for (int i = 0; i < count; i++) {
        buffer.writeln(extraLines[i]);
      }
      throw new StateError(buffer.toString());
    }
  }

  /**
   * Parse the given [logContent] into a list of log entries.
   */
  void _parseLogContent(List<String> logContent) {
    if (_isSessionData(logContent)) {
      if (logContent[0].startsWith('-----')) {
        logContent.removeAt(0);
      }
      int lastIndex = logContent.length - 1;
      if (logContent[lastIndex].startsWith('extraction complete')) {
        logContent.removeAt(lastIndex);
      }
    } else {
      _mergeEntries(logContent);
    }
    logEntries = <LogEntry>[];
    analysisRanges = <EntryRange>[];
    NotificationEntry analysisStartEntry = null;
    int analysisStartIndex = -1;
    NotificationEntry pubStartEntry = null;
    for (String line in logContent) {
      LogEntry entry = new LogEntry.from(logEntries.length, line);
      if (entry != null) {
        logEntries.add(entry);
        if (entry is RequestEntry) {
          _requestMap[entry.id] = entry;
        } else if (entry is ResponseEntry) {
          _responseMap[entry.id] = entry;
          RequestEntry request = _requestMap[entry.id];
          _pairedEntries[entry] = request;
          _pairedEntries[request] = entry;
        } else if (entry is NotificationEntry) {
          if (entry.isServerStatus) {
            var analysisStatus = entry.param('analysis');
            if (analysisStatus is Map) {
              if (analysisStatus['isAnalyzing']) {
                if (analysisStartEntry != null) {
                  analysisStartEntry.recordProblem(
                      'Analysis started without being terminated.');
                }
                analysisStartEntry = entry;
                analysisStartIndex = logEntries.length - 1;
              } else {
                if (analysisStartEntry == null) {
                  entry.recordProblem(
                      'Analysis terminated without being started.');
                } else {
                  int analysisEnd = logEntries.length - 1;
                  analysisRanges
                      .add(new EntryRange(analysisStartIndex, analysisEnd));
                  _pairedEntries[entry] = analysisStartEntry;
                  _pairedEntries[analysisStartEntry] = entry;
                  analysisStartEntry = null;
                  analysisStartIndex = -1;
                }
              }
            }
            var pubStatus = entry.param('pub');
            if (pubStatus is Map) {
              if (pubStatus['isListingPackageDirs']) {
                if (pubStartEntry != null) {
                  pubStartEntry.recordProblem(
                      'Pub started without previous being terminated.');
                }
                pubStartEntry = entry;
              } else {
                if (pubStartEntry == null) {
                  entry.recordProblem('Pub terminated without being started.');
                } else {
                  _pairedEntries[entry] = pubStartEntry;
                  _pairedEntries[pubStartEntry] = entry;
                  pubStartEntry = null;
                }
              }
            }
          } else if (entry.event == 'completion.results') {
            String id = entry.param('id');
            if (id != null) {
              _completionMap
                  .putIfAbsent(id, () => new List<NotificationEntry>())
                  .add(entry);
            }
          }
        } else if (entry is PluginRequestEntry) {
          _pluginRequestMap[entry.id] = entry;
        } else if (entry is PluginResponseEntry) {
          _pluginResponseMap[entry.id] = entry;
          PluginRequestEntry request = _pluginRequestMap[entry.id];
          _pairedEntries[entry] = request;
          _pairedEntries[request] = entry;
        }
      }
    }
    if (analysisStartEntry != null) {
      analysisStartEntry
          .recordProblem('Analysis started without being terminated.');
    }
    if (pubStartEntry != null) {
      pubStartEntry
          .recordProblem('Pub started without previous being terminated.');
    }
  }
}

/**
 * A log entry that has a single JSON encoded component following the time stamp
 * and entry kind.
 */
abstract class JsonBasedEntry extends LogEntry {
  /**
   * The HTML string used to indent text when formatting the JSON [data].
   */
  static const String singleIndent = '&nbsp;&nbsp;&nbsp;';

  /**
   * The decoded form of the JSON encoded component.
   */
  final Map data;

  /**
   * Initialize a newly created log entry to have the given [timeStamp] and
   * [data].
   */
  JsonBasedEntry(int index, int timeStamp, this.data) : super(index, timeStamp);

  @override
  void _appendDetails(StringBuffer buffer) {
    super._appendDetails(buffer);
    _format(buffer, '', data);
  }

  /**
   * Encode any character in the given [string] that would prevent source code
   * from being displayed correctly: end of line markers and spaces.
   */
  String _encodeSourceCode(String string) {
    // TODO(brianwilkerson) This method isn't working completely. Some source
    // code produces an error of
    // "log?start=3175:261 Uncaught SyntaxError: missing ) after argument list"
    // in the sample log I was using.
    StringBuffer buffer = new StringBuffer();
    int length = string.length;
    int index = 0;
    while (index < length) {
      int char = string.codeUnitAt(index);
      index++;
      // TODO(brianwilkerson) Handle tabs and other special characters.
      if (char == '\r'.codeUnitAt(0)) {
        if (index < length && string.codeUnitAt(index) == '\n'.codeUnitAt(0)) {
          index++;
        }
        buffer.write('<br>');
      } else if (char == '\n'.codeUnitAt(0)) {
        buffer.write('<br>');
      } else if (char == ' '.codeUnitAt(0)) {
        // Encode all spaces in order to accurately reproduce the original
        // source code when displaying it.
        buffer.write('&nbsp;');
      } else {
        buffer.writeCharCode(char);
      }
    }
    return buffer.toString();
  }

  /**
   * Write an HTML representation the given JSON [object] to the given [buffer],
   * using the given [indent] to make the output more readable.
   */
  void _format(StringBuffer buffer, String indent, Object object) {
    if (object is String) {
      buffer.write('"');
      buffer.write(_encodeSourceCode(object));
      buffer.write('"');
    } else if (object is int || object is bool) {
      buffer.write(object);
    } else if (object is Map) {
      buffer.write('{<br>');
      object.forEach((Object key, Object value) {
        String newIndent = indent + singleIndent;
        buffer.write(newIndent);
        _format(buffer, newIndent, key);
        buffer.write(' : ');
        _format(buffer, newIndent, value);
        buffer.write('<br>');
      });
      buffer.write(indent);
      buffer.write('}');
    } else if (object is List) {
      buffer.write('[<br>');
      object.forEach((Object element) {
        String newIndent = indent + singleIndent;
        buffer.write(newIndent);
        _format(buffer, newIndent, element);
        buffer.write('<br>');
      });
      buffer.write(indent);
      buffer.write(']');
    }
  }
}

/**
 * A log entry representing a communication between the server and a plugin.
 */
abstract class JsonBasedPluginEntry extends JsonBasedEntry
    with PluginEntryMixin {
  /**
   * The components describing the plugin associated with this entry.
   */
  final List<String> pluginData;

  /**
   * Initialize a newly created entry to have the given [timeStamp] and
   * [notificationData] and to be associated with the plugin with the given
   * [pluginData].
   */
  JsonBasedPluginEntry(
      int index, int timeStamp, Map notificationData, this.pluginData)
      : super(index, timeStamp, notificationData);
}

/**
 * A single entry in an instrumentation log.
 */
abstract class LogEntry {
  /**
   * The character used to separate fields within an entry.
   */
  static final int fieldSeparator = ':'.codeUnitAt(0);

  /**
   * A regular expression that will match the beginning of a valid log entry.
   */
  static final RegExp entryRegExp = new RegExp('[0-9]+\\:');

  /**
   * A table mapping kinds to the names of those kinds.
   */
  static final Map<String, String> kindMap = {
    'Err': 'Error',
    'Ex': 'Exception',
    'Log': 'Log message',
    'Mal': 'Malformed entry',
    'Noti': 'Notification',
    'Read': 'Read file',
    'Req': 'Request',
    'Res': 'Response',
    'Perf': 'Performance data',
    'SPResult': 'Subprocess result',
    'SPStart': 'Subprocess start',
    'Task': 'Task',
    'Ver': 'Version information',
    'Watch': 'Watch event',
  };

  /**
   * The index of this entry in the log file.
   */
  final int index;

  /**
   * The time at which the entry occurred.
   */
  final int timeStamp;

  /**
   * A list containing the descriptions of problems that were found while
   * processing the log file, or `null` if no problems were found.
   */
  List<String> _problems = null;

  /**
   * Initialize a newly created log entry with the given [timeStamp].
   */
  LogEntry(this.index, this.timeStamp);

  /**
   * Create a log entry from the given encoded form of the [entry].
   */
  factory LogEntry.from(int index, String entry) {
    if (entry.isEmpty) {
      return null;
    }
    try {
      List<String> components = _parseComponents(entry);
      int timeStamp;
      String component = components[0];
      if (component.startsWith('~')) {
        component = component.substring(1);
      }
      timeStamp = int.parse(component);
      String entryKind = components[1];
      if (entryKind == InstrumentationService.TAG_ANALYSIS_TASK) {
        return new TaskEntry(index, timeStamp, components[2], components[3]);
      } else if (entryKind == InstrumentationService.TAG_ERROR) {
        return new ErrorEntry(
            index, timeStamp, entryKind, components.sublist(2));
      } else if (entryKind == InstrumentationService.TAG_EXCEPTION) {
        return new ExceptionEntry(
            index, timeStamp, entryKind, components.sublist(2));
      } else if (entryKind == InstrumentationService.TAG_FILE_READ) {
        // Fall through
      } else if (entryKind == InstrumentationService.TAG_LOG_ENTRY) {
        // Fall through
      } else if (entryKind == InstrumentationService.TAG_NOTIFICATION) {
        Map requestData = json.decode(components[2]);
        return new NotificationEntry(index, timeStamp, requestData);
      } else if (entryKind == InstrumentationService.TAG_PERFORMANCE) {
        // Fall through
      } else if (entryKind == InstrumentationService.TAG_PLUGIN_ERROR) {
        return new PluginErrorEntry(index, timeStamp, entryKind,
            components.sublist(2, 4), components.sublist(4));
      } else if (entryKind == InstrumentationService.TAG_PLUGIN_EXCEPTION) {
        return new PluginExceptionEntry(index, timeStamp, entryKind,
            components.sublist(2, 5), components.sublist(5));
      } else if (entryKind == InstrumentationService.TAG_PLUGIN_NOTIFICATION) {
        Map requestData = json.decode(components[2]);
        return new PluginNotificationEntry(
            index, timeStamp, requestData, components.sublist(3));
      } else if (entryKind == InstrumentationService.TAG_PLUGIN_REQUEST) {
        Map requestData = json.decode(components[2]);
        return new PluginRequestEntry(
            index, timeStamp, requestData, components.sublist(3));
      } else if (entryKind == InstrumentationService.TAG_PLUGIN_RESPONSE) {
        Map responseData = json.decode(components[2]);
        return new PluginResponseEntry(
            index, timeStamp, responseData, components.sublist(3));
      } else if (entryKind == InstrumentationService.TAG_PLUGIN_TIMEOUT) {
        return new PluginErrorEntry(index, timeStamp, entryKind,
            components.sublist(2, 3), components.sublist(3));
      } else if (entryKind == InstrumentationService.TAG_REQUEST) {
        Map requestData = json.decode(components[2]);
        return new RequestEntry(index, timeStamp, requestData);
      } else if (entryKind == InstrumentationService.TAG_RESPONSE) {
        Map responseData = json.decode(components[2]);
        return new ResponseEntry(index, timeStamp, responseData);
      } else if (entryKind == InstrumentationService.TAG_SUBPROCESS_START) {
        // Fall through
      } else if (entryKind == InstrumentationService.TAG_SUBPROCESS_RESULT) {
        // Fall through
      } else if (entryKind == InstrumentationService.TAG_VERSION) {
        // Fall through
      } else if (entryKind == InstrumentationService.TAG_WATCH_EVENT) {
        // Fall through
      }
      return new GenericEntry(
          index, timeStamp, entryKind, components.sublist(2));
    } catch (exception) {
      LogEntry logEntry = new MalformedLogEntry(index, entry);
      logEntry.recordProblem(exception.toString());
      return logEntry;
    }
  }

  /**
   * Return `true` if any problems were found while processing the log file.
   */
  bool get hasProblems => _problems != null;

  /**
   * Return the value of the component used to indicate the kind of the entry.
   * This is the abbreviation recorded in the entry.
   */
  String get kind;

  /**
   * Return a human-readable representation of the kind of this entry.
   */
  String get kindName => kindMap[kind] ?? kind;

  /**
   * Return a list containing the descriptions of problems that were found while
   * processing the log file, or `null` if no problems were found.
   */
  List<String> get problems => _problems;

  /**
   * Return a date that is equivalent to the [timeStamp].
   */
  DateTime get toTime => new DateTime.fromMillisecondsSinceEpoch(timeStamp);

  /**
   * Return an HTML representation of the details of the entry.
   */
  String details() {
    StringBuffer buffer = new StringBuffer();
    _appendDetails(buffer);
    return buffer.toString();
  }

  /**
   * Record that the given [problem] was found while processing the log file.
   */
  void recordProblem(String problem) {
    _problems ??= <String>[];
    _problems.add(problem);
  }

  /**
   * Append details related to this entry to the given [buffer].
   */
  void _appendDetails(StringBuffer buffer) {
    if (_problems != null) {
      for (String problem in _problems) {
        buffer.write('<p><span class="error">$problem</span></p>');
      }
    }
  }

  /**
   * Parse the given encoded form of the [entry] into a list of components. The
   * first component is always the time stamp for when the entry was generated.
   * The second component is always the kind of the entry. The remaining
   * components depend on the kind of the entry. Return the components that were
   * parsed.
   */
  static List<String> _parseComponents(String entry) {
    List<String> components = <String>[];
    StringBuffer component = new StringBuffer();
    int length = entry.length;
    for (int i = 0; i < length; i++) {
      int char = entry.codeUnitAt(i);
      if (char == fieldSeparator) {
        if (entry.codeUnitAt(i + 1) == fieldSeparator) {
          component.write(':');
          i++;
        } else {
          components.add(component.toString());
          component.clear();
        }
      } else {
        component.writeCharCode(char);
      }
    }
    components.add(component.toString());
    return components;
  }
}

/**
 * A representation of a malformed log entry.
 */
class MalformedLogEntry extends LogEntry {
  final String entry;

  MalformedLogEntry(int index, this.entry) : super(index, -1);

  @override
  String get kind => 'Mal';

  @override
  void _appendDetails(StringBuffer buffer) {
    super._appendDetails(buffer);
    buffer.write(entry);
    buffer.write('<br>');
  }
}

/**
 * A log entry representing a notification that was sent from the server to the
 * client.
 */
class NotificationEntry extends JsonBasedEntry {
  /**
   * Initialize a newly created response to have the given [timeStamp] and
   * [notificationData].
   */
  NotificationEntry(int index, int timeStamp, Map notificationData)
      : super(index, timeStamp, notificationData);

  /**
   * Return the event field of the request.
   */
  String get event => data['event'];

  /**
   * Return `true` if this is a server error notification.
   */
  bool get isServerError => event == 'server.error';

  /**
   * Return `true` if this is a server status notification.
   */
  bool get isServerStatus => event == 'server.status';

  @override
  String get kind => 'Noti';

  /**
   * Return the value of the parameter with the given [parameterName], or `null`
   * if there is no such parameter.
   */
  dynamic param(String parameterName) {
    var parameters = data['params'];
    if (parameters is Map) {
      return parameters[parameterName];
    }
    return null;
  }
}

/**
 * A log entry representing a communication between the server and a plugin.
 */
mixin PluginEntryMixin {
  /**
   * The components describing the plugin associated with this entry.
   */
  List<String> get pluginData;

  /**
   * The id of the plugin associated with this entry.
   */
  String get pluginId => pluginData[0];

  /**
   * The name of the plugin associated with this entry.
   */
  String get pluginName => pluginData[1];

  /**
   * The version of the plugin associated with this entry.
   */
  String get pluginVersion => pluginData[2];

  /**
   * Return a shortened version of the plugin id.
   */
  String get shortPluginId {
    int index = pluginId.lastIndexOf(path.separator);
    if (index > 0) {
      return pluginId.substring(index + 1);
    }
    return pluginId;
  }
}

/**
 * A log entry representing an PluginErr entry.
 */
class PluginErrorEntry extends GenericPluginEntry {
  /**
   * Initialize a newly created log entry.
   */
  PluginErrorEntry(int index, int timeStamp, String entryKind,
      List<String> components, List<String> pluginData)
      : super(index, timeStamp, entryKind, components, pluginData);
}

/**
 * A log entry representing an PluginEx entry.
 */
class PluginExceptionEntry extends GenericPluginEntry {
  /**
   * Initialize a newly created log entry.
   */
  PluginExceptionEntry(int index, int timeStamp, String entryKind,
      List<String> components, List<String> pluginData)
      : super(index, timeStamp, entryKind, components, pluginData);
}

/**
 * A log entry representing a notification that was sent from a plugin to the
 * server.
 */
class PluginNotificationEntry extends JsonBasedPluginEntry {
  /**
   * Initialize a newly created notification to have the given [timeStamp] and
   * [notificationData].
   */
  PluginNotificationEntry(
      int index, int timeStamp, Map notificationData, List<String> pluginData)
      : super(index, timeStamp, notificationData, pluginData);

  /**
   * Return the event field of the notification.
   */
  String get event => data['event'];

  @override
  String get kind => 'PluginNoti';

  /**
   * Return the value of the parameter with the given [parameterName], or `null`
   * if there is no such parameter.
   */
  dynamic param(String parameterName) {
    var parameters = data['params'];
    if (parameters is Map) {
      return parameters[parameterName];
    }
    return null;
  }
}

/**
 * A log entry representing a request that was sent from the server to a plugin.
 */
class PluginRequestEntry extends JsonBasedPluginEntry {
  /**
   * Initialize a newly created response to have the given [timeStamp] and
   * [requestData].
   */
  PluginRequestEntry(
      int index, int timeStamp, Map requestData, List<String> pluginData)
      : super(index, timeStamp, requestData, pluginData);

  /**
   * Return the id field of the request.
   */
  String get id => data['id'];

  @override
  String get kind => 'PluginReq';

  /**
   * Return the method field of the request.
   */
  String get method => data['method'];

  /**
   * Return the value of the parameter with the given [parameterName], or `null`
   * if there is no such parameter.
   */
  dynamic param(String parameterName) {
    var parameters = data['params'];
    if (parameters is Map) {
      return parameters[parameterName];
    }
    return null;
  }
}

/**
 * A log entry representing a response that was sent from a plugin to the
 * server.
 */
class PluginResponseEntry extends JsonBasedPluginEntry {
  /**
   * Initialize a newly created response to have the given [timeStamp] and
   * [responseData].
   */
  PluginResponseEntry(
      int index, int timeStamp, Map responseData, List<String> pluginData)
      : super(index, timeStamp, responseData, pluginData);

  /**
   * Return the id field of the response.
   */
  String get id => data['id'];

  @override
  String get kind => 'PluginRes';

  /**
   * Return the value of the result with the given [resultName], or `null`  if
   * there is no such result.
   */
  dynamic result(String resultName) {
    var results = data['result'];
    if (results is Map) {
      return results[resultName];
    }
    return null;
  }
}

/**
 * A log entry representing a request that was sent from the client to the
 * server.
 */
class RequestEntry extends JsonBasedEntry {
  /**
   * Initialize a newly created response to have the given [timeStamp] and
   * [requestData].
   */
  RequestEntry(int index, int timeStamp, Map requestData)
      : super(index, timeStamp, requestData);

  /**
   * Return the clientRequestTime field of the request.
   */
  int get clientRequestTime => data['clientRequestTime'];

  /**
   * Return the id field of the request.
   */
  String get id => data['id'];

  @override
  String get kind => 'Req';

  /**
   * Return the method field of the request.
   */
  String get method => data['method'];

  /**
   * Return the value of the parameter with the given [parameterName], or `null`
   * if there is no such parameter.
   */
  dynamic param(String parameterName) {
    var parameters = data['params'];
    if (parameters is Map) {
      return parameters[parameterName];
    }
    return null;
  }
}

/**
 * A log entry representing a response that was sent from the server to the
 * client.
 */
class ResponseEntry extends JsonBasedEntry {
  /**
   * Initialize a newly created response to have the given [timeStamp] and
   * [responseData].
   */
  ResponseEntry(int index, int timeStamp, Map responseData)
      : super(index, timeStamp, responseData);

  /**
   * Return the id field of the response.
   */
  String get id => data['id'];

  @override
  String get kind => 'Res';

  /**
   * Return the value of the result with the given [resultName], or `null`  if
   * there is no such result.
   */
  dynamic result(String resultName) {
    var results = data['result'];
    if (results is Map) {
      return results[resultName];
    }
    return null;
  }
}

class TaskEntry extends LogEntry {
  /**
   * The path to the directory at the root of the context in which analysis was
   * being performed.
   */
  final String context;

  /**
   * A description of the task that was performed.
   */
  final String description;

  /**
   * The name of the class implementing the task.
   */
  String _taskName = null;

  /**
   * The description of the target of the task.
   */
  String _target = null;

  /**
   * Initialize a newly created entry with the given [index] and [timeStamp] to
   * represent the execution of an analysis task in the given [context] that is
   * described by the given [description].
   */
  TaskEntry(int index, int timeStamp, this.context, this.description)
      : super(index, timeStamp);

  @override
  String get kind => 'Task';

  /**
   * Return the description of the target of the task.
   */
  String get target {
    if (_target == null) {
      _splitDescription();
    }
    return _target;
  }

  /**
   * Return the name of the class implementing the task.
   */
  String get taskName {
    if (_taskName == null) {
      _splitDescription();
    }
    return _taskName;
  }

  @override
  void _appendDetails(StringBuffer buffer) {
    super._appendDetails(buffer);
    buffer.write('<span class="label">Context:</span> ');
    buffer.write(context);
    buffer.write('<br><span class="label">Description: </span> ');
    buffer.write(description);
  }

  /**
   * Split the description to get the task name and target description.
   */
  void _splitDescription() {
    int index = description.indexOf(' ');
    if (index < 0) {
      _taskName = '';
    } else {
      _taskName = description.substring(0, index);
    }
    index = description.lastIndexOf(' ');
    _target = description.substring(index + 1);
    int slash = context.lastIndexOf('/');
    if (slash < 0) {
      slash = context.lastIndexOf('\\');
    }
    if (slash >= 0) {
      String prefix = context.substring(0, slash);
      _target = _target.replaceAll(prefix, '...');
    }
  }
}
