// Copyright (c) 2014, 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:async';
import 'dart:convert';

import 'package:analyzer/src/task/api/model.dart';

/**
 * A container with analysis performance constants.
 */
class AnalysisPerformanceKind {
  static const String FULL = 'analysis_full';
  static const String INCREMENTAL = 'analysis_incremental';
}

/**
 * The interface used by client code to communicate with an instrumentation
 * server.
 */
abstract class InstrumentationServer {
  /**
   * A user-friendly description of this instrumentation server.
   */
  String get describe;

  /**
   * Return the identifier used to identify the current session.
   */
  String get sessionId;

  /**
   * Pass the given [message] to the instrumentation server so that it will be
   * logged with other messages.
   *
   * This method should be used for most logging.
   */
  void log(String message);

  /**
   * Pass the given [message] to the instrumentation server so that it will be
   * logged with other messages.
   *
   * This method should only be used for logging high priority messages, such as
   * exceptions that cause the server to shutdown.
   */
  void logWithPriority(String message);

  /**
   * Signal that the client is done communicating with the instrumentation
   * server. This method should be invoked exactly one time and no other methods
   * should be invoked on this instance after this method has been invoked.
   */
  Future shutdown();
}

/**
 * The interface used by client code to communicate with an instrumentation
 * server by wrapping an [InstrumentationServer].
 */
class InstrumentationService {
  /**
   * An instrumentation service that will not log any instrumentation data.
   */
  static final InstrumentationService NULL_SERVICE =
      new InstrumentationService(null);

  static const String TAG_ANALYSIS_TASK = 'Task';
  static const String TAG_ERROR = 'Err';
  static const String TAG_EXCEPTION = 'Ex';
  static const String TAG_FILE_READ = 'Read';
  static const String TAG_INFO = 'Info';
  static const String TAG_LOG_ENTRY = 'Log';
  static const String TAG_NOTIFICATION = 'Noti';
  static const String TAG_PERFORMANCE = 'Perf';
  static const String TAG_PLUGIN_ERROR = 'PluginErr';
  static const String TAG_PLUGIN_EXCEPTION = 'PluginEx';
  static const String TAG_PLUGIN_NOTIFICATION = 'PluginNoti';
  static const String TAG_PLUGIN_REQUEST = 'PluginReq';
  static const String TAG_PLUGIN_RESPONSE = 'PluginRes';
  static const String TAG_PLUGIN_TIMEOUT = 'PluginTo';
  static const String TAG_REQUEST = 'Req';
  static const String TAG_RESPONSE = 'Res';
  static const String TAG_SUBPROCESS_START = 'SPStart';
  static const String TAG_SUBPROCESS_RESULT = 'SPResult';
  static const String TAG_VERSION = 'Ver';
  static const String TAG_WATCH_EVENT = 'Watch';

  /**
   * The instrumentation server used to communicate with the server, or `null`
   * if instrumentation data should not be logged.
   */
  InstrumentationServer _instrumentationServer;

  /**
   * Counter used to generate unique ID's for [logSubprocessStart].
   */
  int _subprocessCounter = 0;

  /**
   * Initialize a newly created instrumentation service to communicate with the
   * given [_instrumentationServer].
   */
  InstrumentationService(this._instrumentationServer);

  InstrumentationServer get instrumentationServer => _instrumentationServer;

  /**
   * Return `true` if this [InstrumentationService] was initialized with a
   * non-`null` server (and hence instrumentation is active).
   */
  bool get isActive => _instrumentationServer != null;

  /**
   * Return the identifier used to identify the current session.
   */
  String get sessionId => _instrumentationServer?.sessionId ?? '';

  /**
   * The current time, expressed as a decimal encoded number of milliseconds.
   */
  String get _timestamp => new DateTime.now().millisecondsSinceEpoch.toString();

  /**
   * Log that the given analysis [task] is being performed in the given
   * [context].
   */
  void logAnalysisTask(String context, AnalysisTask task) {
    if (_instrumentationServer != null) {
      _instrumentationServer
          .log(_join([TAG_ANALYSIS_TASK, context, task.description]));
    }
  }

  /**
   * Log the fact that an error, described by the given [message], has occurred.
   */
  void logError(String message) {
    _log(TAG_ERROR, message);
  }

  /**
   * Log that the given non-priority [exception] was thrown, with the given
   * [stackTrace].
   */
  void logException(dynamic exception, StackTrace stackTrace) {
    if (_instrumentationServer != null) {
      String message = _toString(exception);
      String trace = _toString(stackTrace);
      _instrumentationServer.log(_join([TAG_EXCEPTION, message, trace]));
    }
  }

  /**
   * Log that the contents of the file with the given [path] were read. The file
   * had the given [content] and [modificationTime].
   */
  void logFileRead(String path, int modificationTime, String content) {
    if (_instrumentationServer != null) {
      String timeStamp = _toString(modificationTime);
      _instrumentationServer
          .log(_join([TAG_FILE_READ, path, timeStamp, content]));
    }
  }

  /**
   * Log unstructured text information for debugging purposes.
   */
  void logInfo(String message) => _log(TAG_INFO, message);

  /**
   * Log that a log entry that was written to the analysis engine's log. The log
   * entry has the given [level] and [message], and was created at the given
   * [time].
   */
  void logLogEntry(String level, DateTime time, String message,
      Object exception, StackTrace stackTrace) {
    if (_instrumentationServer != null) {
      String timeStamp =
          time == null ? 'null' : time.millisecondsSinceEpoch.toString();
      String exceptionText = exception.toString();
      String stackTraceText = stackTrace.toString();
      _instrumentationServer.log(_join([
        TAG_LOG_ENTRY,
        level,
        timeStamp,
        message,
        exceptionText,
        stackTraceText
      ]));
    }
  }

  /**
   * Log that a notification has been sent to the client.
   */
  void logNotification(String notification) {
    _log(TAG_NOTIFICATION, notification);
  }

  /**
   * Log the given performance fact.
   */
  void logPerformance(String kind, Stopwatch sw, String message) {
    sw.stop();
    String elapsed = sw.elapsedMilliseconds.toString();
    if (_instrumentationServer != null) {
      _instrumentationServer
          .log(_join([TAG_PERFORMANCE, kind, elapsed, message]));
    }
  }

  /**
   * Log the fact that an error, described by the given [message], was reported
   * by the given [plugin].
   */
  void logPluginError(
      PluginData plugin, String code, String message, String stackTrace) {
    if (_instrumentationServer != null) {
      List<String> fields = <String>[
        TAG_PLUGIN_ERROR,
        code,
        message,
        stackTrace
      ];
      plugin.addToFields(fields);
      _instrumentationServer.log(_join(fields));
    }
  }

  /**
   * Log that the given non-priority [exception] was thrown, with the given
   * [stackTrace] by the given [plugin].
   */
  void logPluginException(
      PluginData plugin, dynamic exception, StackTrace stackTrace) {
    if (_instrumentationServer != null) {
      List<String> fields = <String>[
        TAG_PLUGIN_EXCEPTION,
        _toString(exception),
        _toString(stackTrace)
      ];
      plugin.addToFields(fields);
      _instrumentationServer.log(_join(fields));
    }
  }

  void logPluginNotification(String pluginId, String notification) {
    if (_instrumentationServer != null) {
      _instrumentationServer.log(
          _join([TAG_PLUGIN_NOTIFICATION, notification, pluginId, '', '']));
    }
  }

  void logPluginRequest(String pluginId, String request) {
    if (_instrumentationServer != null) {
      _instrumentationServer
          .log(_join([TAG_PLUGIN_REQUEST, request, pluginId, '', '']));
    }
  }

  void logPluginResponse(String pluginId, String response) {
    if (_instrumentationServer != null) {
      _instrumentationServer
          .log(_join([TAG_PLUGIN_RESPONSE, response, pluginId, '', '']));
    }
  }

  /**
   * Log that the given [plugin] took too long to execute the given [request].
   * This doesn't necessarily imply that there is a problem with the plugin,
   * only that this particular response was not included in the data returned
   * to the client.
   */
  void logPluginTimeout(PluginData plugin, String request) {
    if (_instrumentationServer != null) {
      List<String> fields = <String>[TAG_PLUGIN_TIMEOUT, request];
      plugin.addToFields(fields);
      _instrumentationServer.log(_join(fields));
    }
  }

  /**
   * Log that the given priority [exception] was thrown, with the given
   * [stackTrace].
   */
  void logPriorityException(dynamic exception, StackTrace stackTrace) {
    if (_instrumentationServer != null) {
      String message = _toString(exception);
      String trace = _toString(stackTrace);
      _instrumentationServer
          .logWithPriority(_join([TAG_EXCEPTION, message, trace]));
    }
  }

  /**
   * Log that a request has been sent to the client.
   */
  void logRequest(String request) {
    _log(TAG_REQUEST, request);
  }

  /**
   * Log that a response has been sent to the client.
   */
  void logResponse(String response) {
    _log(TAG_RESPONSE, response);
  }

  /**
   * Log the result of executing a subprocess.  [subprocessId] should be the
   * unique ID returned by [logSubprocessStart].
   */
  void logSubprocessResult(
      int subprocessId, int exitCode, String stdout, String stderr) {
    if (_instrumentationServer != null) {
      _instrumentationServer.log(_join([
        TAG_SUBPROCESS_RESULT,
        subprocessId.toString(),
        exitCode.toString(),
        json.encode(stdout),
        json.encode(stderr)
      ]));
    }
  }

  /**
   * Log that the given subprocess is about to be executed.  Returns a unique
   * identifier that can be used to identify the subprocess for later log
   * entries.
   */
  int logSubprocessStart(
      String executablePath, List<String> arguments, String workingDirectory) {
    int subprocessId = _subprocessCounter++;
    if (_instrumentationServer != null) {
      _instrumentationServer.log(_join([
        TAG_SUBPROCESS_START,
        subprocessId.toString(),
        executablePath,
        workingDirectory,
        json.encode(arguments)
      ]));
    }
    return subprocessId;
  }

  /**
   * Signal that the client has started analysis server.
   * This method should be invoked exactly one time.
   */
  void logVersion(String uuid, String clientId, String clientVersion,
      String serverVersion, String sdkVersion) {
    String normalize(String value) =>
        value != null && value.isNotEmpty ? value : 'unknown';

    if (_instrumentationServer != null) {
      _instrumentationServer.logWithPriority(_join([
        TAG_VERSION,
        uuid,
        normalize(clientId),
        normalize(clientVersion),
        serverVersion,
        sdkVersion
      ]));
    }
  }

  /**
   * Log that the file system watcher sent an event. The [folderPath] is the
   * path to the folder containing the changed file, the [filePath] is the path
   * of the file that changed, and the [changeType] indicates what kind of
   * change occurred.
   */
  void logWatchEvent(String folderPath, String filePath, String changeType) {
    if (_instrumentationServer != null) {
      _instrumentationServer
          .log(_join([TAG_WATCH_EVENT, folderPath, filePath, changeType]));
    }
  }

  /**
   * Signal that the client is done communicating with the instrumentation
   * server. This method should be invoked exactly one time and no other methods
   * should be invoked on this instance after this method has been invoked.
   */
  Future shutdown() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    if (_instrumentationServer != null) {
      await _instrumentationServer.shutdown();
      _instrumentationServer = null;
    }
  }

  /**
   * Write an escaped version of the given [field] to the given [buffer].
   */
  void _escape(StringBuffer buffer, String field) {
    int index = field.indexOf(':');
    if (index < 0) {
      buffer.write(field);
      return;
    }
    int start = 0;
    while (index >= 0) {
      buffer.write(field.substring(start, index));
      buffer.write('::');
      start = index + 1;
      index = field.indexOf(':', start);
    }
    buffer.write(field.substring(start));
  }

  /**
   * Return the result of joining the values of the given fields, escaping the
   * separator character by doubling it.
   */
  String _join(List<String> fields) {
    StringBuffer buffer = new StringBuffer();
    buffer.write(_timestamp);
    int length = fields.length;
    for (int i = 0; i < length; i++) {
      buffer.write(':');
      _escape(buffer, fields[i] ?? 'null');
    }
    return buffer.toString();
  }

  /**
   * Log the given message with the given tag.
   */
  void _log(String tag, String message) {
    if (_instrumentationServer != null) {
      _instrumentationServer.log(_join([tag, message]));
    }
  }

  /**
   * Convert the given [object] to a string.
   */
  String _toString(Object object) {
    if (object == null) {
      return 'null';
    }
    return object.toString();
  }
}

/**
 * An [InstrumentationServer] that sends messages to multiple instances.
 */
class MulticastInstrumentationServer implements InstrumentationServer {
  final List<InstrumentationServer> _servers;

  MulticastInstrumentationServer(this._servers);

  @override
  String get describe {
    return _servers
        .map((InstrumentationServer server) => server.describe)
        .join("\n");
  }

  @override
  String get sessionId => _servers[0].sessionId;

  @override
  void log(String message) {
    for (InstrumentationServer server in _servers) {
      server.log(message);
    }
  }

  @override
  void logWithPriority(String message) {
    for (InstrumentationServer server in _servers) {
      server.logWithPriority(message);
    }
  }

  @override
  Future shutdown() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    for (InstrumentationServer server in _servers) {
      await server.shutdown();
    }
  }
}

/**
 * Information about a plugin.
 */
class PluginData {
  /**
   * The id used to uniquely identify the plugin.
   */
  final String pluginId;

  /**
   * The name of the plugin.
   */
  final String name;

  /**
   * The version of the plugin.
   */
  final String version;

  /**
   * Initialize a newly created set of data about a plugin.
   */
  PluginData(this.pluginId, this.name, this.version);

  /**
   * Add the information about the plugin to the list of [fields] to be sent to
   * the instrumentation server.
   */
  void addToFields(List<String> fields) {
    fields.add(pluginId);
    fields.add(name ?? '');
    fields.add(version ?? '');
  }
}
