// Copyright (c) 2019, 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 'package:analyzer/instrumentation/logger.dart';
import 'package:analyzer/instrumentation/plugin_data.dart';
import 'package:analyzer/instrumentation/service.dart';

/// A class to adapt an [InstrumentationService] into a log using an [InstrumentationLogger].
class InstrumentationLogAdapter implements InstrumentationService {
  static const String TAG_ERROR = 'Err';
  static const String TAG_EXCEPTION = 'Ex';
  static const String TAG_INFO = 'Info';
  static const String TAG_LOG_ENTRY = 'Log';
  static const String TAG_NOTIFICATION = 'Noti';
  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_VERSION = 'Ver';
  static const String TAG_WATCH_EVENT = 'Watch';

  /// A logger used to log instrumentation in string format.
  final InstrumentationLogger _instrumentationLogger;

  /// Initialize a newly created instrumentation service to communicate with the
  /// given [_instrumentationLogger].
  InstrumentationLogAdapter(this._instrumentationLogger);

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

  @override
  void logError(String message) => _log(TAG_ERROR, message);

  @override
  void logException(dynamic exception,
      [StackTrace stackTrace,
      List<InstrumentationServiceAttachment> attachments]) {
    if (_instrumentationLogger != null) {
      String message = _toString(exception);
      String trace = _toString(stackTrace);
      _instrumentationLogger.log(_join([TAG_EXCEPTION, message, trace]));
    }
  }

  @override
  void logInfo(String message, [dynamic exception]) =>
      _log(TAG_INFO, message + (exception == null ? "" : exception.toString()));

  @override
  void logLogEntry(String level, DateTime time, String message,
      Object exception, StackTrace stackTrace) {
    if (_instrumentationLogger != null) {
      String timeStamp =
          time == null ? 'null' : time.millisecondsSinceEpoch.toString();
      String exceptionText = exception.toString();
      String stackTraceText = stackTrace.toString();
      _instrumentationLogger.log(_join([
        TAG_LOG_ENTRY,
        level,
        timeStamp,
        message,
        exceptionText,
        stackTraceText
      ]));
    }
  }

  @override
  void logNotification(String notification) =>
      _log(TAG_NOTIFICATION, notification);

  @override
  void logPluginError(
      PluginData plugin, String code, String message, String stackTrace) {
    if (_instrumentationLogger != null) {
      List<String> fields = <String>[
        TAG_PLUGIN_ERROR,
        code,
        message,
        stackTrace
      ];
      plugin.addToFields(fields);
      _instrumentationLogger.log(_join(fields));
    }
  }

  @override
  void logPluginException(
      PluginData plugin, dynamic exception, StackTrace stackTrace) {
    if (_instrumentationLogger != null) {
      List<String> fields = <String>[
        TAG_PLUGIN_EXCEPTION,
        _toString(exception),
        _toString(stackTrace)
      ];
      plugin.addToFields(fields);
      _instrumentationLogger.log(_join(fields));
    }
  }

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

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

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

  @override
  void logPluginTimeout(PluginData plugin, String request) {
    if (_instrumentationLogger != null) {
      List<String> fields = <String>[TAG_PLUGIN_TIMEOUT, request];
      plugin.addToFields(fields);
      _instrumentationLogger.log(_join(fields));
    }
  }

  @override
  void logRequest(String request) => _log(TAG_REQUEST, request);

  @override
  void logResponse(String response) => _log(TAG_RESPONSE, response);

  @override
  void logVersion(String uuid, String clientId, String clientVersion,
      String serverVersion, String sdkVersion) {
    String normalize(String value) =>
        value != null && value.isNotEmpty ? value : 'unknown';

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

  @override
  void logWatchEvent(String folderPath, String filePath, String changeType) {
    if (_instrumentationLogger != null) {
      _instrumentationLogger
          .log(_join([TAG_WATCH_EVENT, folderPath, filePath, changeType]));
    }
  }

  @override
  Future<void> shutdown() => _instrumentationLogger.shutdown();

  /// 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 = 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 (_instrumentationLogger != null) {
      _instrumentationLogger.log(_join([tag, message]));
    }
  }

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