// Copyright (c) 2022, 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:convert';

import 'package:analysis_server/lsp_protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/src/analytics/active_request_data.dart';
import 'package:analysis_server/src/analytics/notification_data.dart';
import 'package:analysis_server/src/analytics/plugin_data.dart';
import 'package:analysis_server/src/analytics/request_data.dart';
import 'package:analysis_server/src/analytics/session_data.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/status/pages.dart';
import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:collection/collection.dart';
import 'package:telemetry/telemetry.dart';

/// An interface for managing and reporting analytics.
///
/// Individual methods can either send an analytics event immediately or can
/// collect and even consolidate information to be reported later. Clients are
/// required to invoke the [shutdown] method before the server shuts down in
/// order to send any cached data.
class AnalyticsManager {
  /// The object used to send analytics.
  final Analytics analytics;

  /// Data about the current session, or `null` if the [startUp] method has not
  /// been invoked.
  SessionData? _sessionData;

  final PluginData _pluginData = PluginData();

  /// A map from the id of a request to data about the request.
  final Map<String, ActiveRequestData> _activeRequests = {};

  /// A map from the name of a request to data about all such requests that have
  /// been responded to.
  final Map<String, RequestData> _completedRequests = {};

  /// A map from the name of a notification to data about all such notifications
  /// that have been handled.
  final Map<String, NotificationData> _completedNotifications = {};

  /// A map from the name of a lint to the number of contexts in which the lint
  /// was enabled.
  final Map<String, int> _lintUsageCounts = {};

  /// A map from the name of a diagnostic to a map whose values are the number
  /// of times that the severity of the diagnostic was changed to the severity
  /// represented by the key.
  final Map<String, Map<String, int>> _severityAdjustments = {};

  /// Initialize a newly created analytics manager to report to the [analytics]
  /// service.
  AnalyticsManager(this.analytics);

  /// Record that the set of plugins known to the [pluginManager] has changed.
  void changedPlugins(PluginManager pluginManager) {
    _pluginData.recordPlugins(pluginManager);
  }

  /// Record the number of [added] folders and [removed] folders.
  void changedWorkspaceFolders(
      {required List<String> added, required List<String> removed}) {
    var requestData =
        _getRequestData(Method.workspace_didChangeWorkspaceFolders.toString());
    requestData.addValue('added', added.length);
    requestData.addValue('removed', removed.length);
  }

  /// Record that the [contexts] have been created.
  void createdAnalysisContexts(List<AnalysisContext> contexts) {
    for (var context in contexts) {
      for (var rule in context.analysisOptions.lintRules) {
        var name = rule.name;
        _lintUsageCounts[name] = (_lintUsageCounts[name] ?? 0) + 1;
      }
      for (var processor in context.analysisOptions.errorProcessors) {
        var severity = processor.severity?.name ?? 'ignore';
        var severityCounts =
            _severityAdjustments.putIfAbsent(processor.code, () => {});
        severityCounts[severity] = (severityCounts[severity] ?? 0) + 1;
      }
    }
  }

  /// Record that the given [notification] was received and has been handled.
  void handledNotificationMessage(
      {required NotificationMessage notification,
      required DateTime startTime,
      required DateTime endTime}) {
    var method = notification.method.toString();
    var requestTime = notification.clientRequestTime;
    var start = startTime.millisecondsSinceEpoch;
    var end = endTime.millisecondsSinceEpoch;
    var data = _completedNotifications.putIfAbsent(
        method, () => NotificationData(method));
    if (requestTime != null) {
      data.latencyTimes.addValue(start - requestTime);
    }
    data.handlingTimes.addValue(end - start);
  }

  /// Record the parameters passed on initialize.
  void initialize(InitializeParams params) {
    var options = LspInitializationOptions(params.initializationOptions);
    var paramNames = <String>[
      if (options.closingLabels) 'closingLabels',
      if (options.flutterOutline) 'flutterOutline',
      if (options.onlyAnalyzeProjectsWithOpenFiles)
        'onlyAnalyzeProjectsWithOpenFiles',
      if (options.outline) 'outline',
      if (options.suggestFromUnimportedLibraries)
        'suggestFromUnimportedLibraries',
    ];
    _sessionData?.initializeParams = paramNames.join(',');
  }

  /// Record the number of [openWorkspacePaths].
  void initialized({required List<String> openWorkspacePaths}) {
    var requestData = _getRequestData(Method.initialized.toString());
    requestData.addValue('openWorkspacePaths', openWorkspacePaths.length);
  }

  /// Record that the given [response] was sent to the client.
  void sentResponse({required Response response}) {
    var sendTime = DateTime.now();
    _recordResponseData(response.id, sendTime);
  }

  /// Record that the given [response] was sent to the client.
  void sentResponseMessage({required ResponseMessage response}) {
    var sendTime = DateTime.now();
    var id = response.id?.asString;
    if (id == null) {
      return;
    }
    _recordResponseData(id, sendTime);
  }

  /// The server is shutting down. Report any accumulated analytics data.
  void shutdown() {
    final sessionData = _sessionData;
    if (sessionData == null) {
      return;
    }
    _sendSessionData(sessionData);
    _sendServerResponseTimes();
    _sendPluginResponseTimes();
    _sendNotificationHandlingTimes();
    _sendLintUsageCounts();
    _sendSeverityAdjustments();

    analytics.waitForLastPing(timeout: Duration(milliseconds: 200)).then((_) {
      analytics.close();
    });
  }

  /// Record data from the given [params].
  void startedGetRefactoring(EditGetRefactoringParams params) {
    var requestData = _getRequestData(EDIT_REQUEST_GET_REFACTORING);
    requestData.addEnumValue(
        EDIT_REQUEST_GET_REFACTORING_KIND, params.kind.name);
  }

  /// Record that the server started working on the give [request] at the given
  /// [startTime].
  void startedRequest({required Request request, required DateTime startTime}) {
    var method = request.method;
    _activeRequests[request.id] =
        ActiveRequestData(method, request.clientRequestTime, startTime);
  }

  /// Record that the server started working on the give [request] at the given
  /// [startTime].
  void startedRequestMessage(
      {required RequestMessage request, required DateTime startTime}) {
    _activeRequests[request.id.asString] = ActiveRequestData(
        request.method.toString(), request.clientRequestTime, startTime);
  }

  /// Record data from the given [params].
  void startedSetAnalysisRoots(AnalysisSetAnalysisRootsParams params) {
    var requestData = _getRequestData(ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS);
    requestData.addValue(
        ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS_INCLUDED, params.included.length);
    requestData.addValue(
        ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS_EXCLUDED, params.excluded.length);
  }

  /// Record data from the given [params].
  void startedSetPriorityFiles(AnalysisSetPriorityFilesParams params) {
    var requestData = _getRequestData(ANALYSIS_REQUEST_SET_PRIORITY_FILES);
    requestData.addValue(
        ANALYSIS_REQUEST_SET_PRIORITY_FILES_FILES, params.files.length);
  }

  /// Record that the server was started at the given [time], that it was passed
  /// the given command-line [arguments], that it was started by the client with
  /// the given [clientId] and [clientVersion], and that it was invoked from an
  /// SDK with the given [sdkVersion].
  void startUp(
      {required DateTime time,
      required List<String> arguments,
      required String clientId,
      required String? clientVersion,
      required String sdkVersion}) {
    _sessionData = SessionData(
        startTime: time,
        commandLineArguments: arguments.join(','),
        clientId: clientId,
        clientVersion: clientVersion ?? '',
        sdkVersion: sdkVersion);
  }

  /// Return an HTML representation of the data that has been recorded.
  String? toHtml(StringBuffer buffer) {
    var sessionData = _sessionData;
    if (sessionData == null) {
      return null;
    }

    void h3(String title) {
      buffer.writeln('<h3>${escape(title)}</h3>');
    }

    void h4(String title) {
      buffer.writeln('<h4>${escape(title)}</h4>');
    }

    void h5(String title) {
      buffer.writeln('<h5>${escape(title)}</h5>');
    }

    void li(String item) {
      buffer.writeln('<li>${escape(item)}</li>');
    }

    List<MapEntry<String, V>> sorted<V>(
            Iterable<MapEntry<String, V>> entries) =>
        entries.sortedBy((entry) => entry.key);

    buffer.writeln('<hr>');

    var endTime = DateTime.now().millisecondsSinceEpoch;
    var duration = endTime - sessionData.startTime.millisecondsSinceEpoch;
    h3('Session data');
    buffer.writeln('<ul>');
    li('clientId: ${sessionData.clientId}');
    li('clientVersion: ${sessionData.clientVersion}');
    li('duration: ${duration.toString()}');
    li('flags: ${sessionData.commandLineArguments}');
    li('parameters: ${sessionData.initializeParams}');
    li('sdkVersion: ${sessionData.sdkVersion}');
    li('plugins: ${_pluginData.usageCountData}');
    buffer.writeln('</ul>');

    if (_completedRequests.isNotEmpty) {
      h3('Server response times');
      var entries = sorted(_completedRequests.entries);
      for (var entry in entries) {
        var data = entry.value;
        h4(data.method);
        buffer.writeln('<ul>');
        li('latency: ${data.latencyTimes.toAnalyticsString()}');
        li('duration: ${data.responseTimes.toAnalyticsString()}');
        for (var field in data.additionalPercentiles.entries) {
          li('${field.key}: ${field.value.toAnalyticsString()}');
        }
        for (var field in data.additionalEnumCounts.entries) {
          li('${field.key}: ${json.encode(field.value)}');
        }
        buffer.writeln('</ul>');
      }
    }

    var responseTimes = PluginManager.pluginResponseTimes;
    if (responseTimes.isNotEmpty) {
      h3('Plugin response times');
      for (var pluginEntry in responseTimes.entries) {
        h4(pluginEntry.key.pluginId);
        var entries = sorted(pluginEntry.value.entries);
        for (var responseEntry in entries) {
          h5(responseEntry.key);
          buffer.writeln('<ul>');
          li('duration: ${responseEntry.value.toAnalyticsString()}');
          buffer.writeln('</ul>');
        }
      }
    }

    if (_completedNotifications.isNotEmpty) {
      h3('Notification handling times');
      buffer.writeln('<ul>');
      var entries = sorted(_completedNotifications.entries);
      for (var entry in entries) {
        var data = entry.value;
        li('latency: ${data.latencyTimes.toAnalyticsString()}');
        li('method: ${data.method}');
        li('duration: ${data.handlingTimes.toAnalyticsString()}');
      }
      buffer.writeln('</ul>');
    }

    if (_lintUsageCounts.isNotEmpty) {
      h3('Lint usage counts');
      buffer.writeln('<ul>');
      li('usageCounts: ${json.encode(_lintUsageCounts)}');
      buffer.writeln('</ul>');
    }

    if (_severityAdjustments.isNotEmpty) {
      h3('Severity adjustments');
      buffer.writeln('<ul>');
      li('adjustmentCounts: ${json.encode(_severityAdjustments)}');
      buffer.writeln('</ul>');
    }

    return buffer.toString();
  }

  /// Return the request data for requests that have the given [method].
  RequestData _getRequestData(String method) {
    return _completedRequests.putIfAbsent(method, () => RequestData(method));
  }

  /// Record that the request with the given [id] was responded to at the given
  /// [sendTime].
  void _recordResponseData(String id, DateTime sendTime) {
    var data = _activeRequests.remove(id);
    if (data == null) {
      return;
    }

    var method = data.method;
    var clientRequestTime = data.clientRequestTime;
    var startTime = data.startTime.millisecondsSinceEpoch;

    var requestData = _getRequestData(method);

    if (clientRequestTime != null) {
      var latencyTime = startTime - clientRequestTime;
      requestData.latencyTimes.addValue(latencyTime);
    }

    var responseTime = sendTime.millisecondsSinceEpoch - startTime;
    requestData.responseTimes.addValue(responseTime);
  }

  void _sendLintUsageCounts() {
    if (_lintUsageCounts.isNotEmpty) {
      analytics.sendEvent('language_server', 'lintUsageCounts', parameters: {
        'usageCounts': json.encode(_lintUsageCounts),
      });
    }
  }

  /// Send information about the notifications handled by the server.
  void _sendNotificationHandlingTimes() {
    for (var data in _completedNotifications.values) {
      analytics.sendEvent('language_server', 'notification', parameters: {
        'latency': data.latencyTimes.toAnalyticsString(),
        'method': data.method,
        'duration': data.handlingTimes.toAnalyticsString(),
      });
    }
  }

  /// Send information about the response times of plugins.
  void _sendPluginResponseTimes() {
    var responseTimes = PluginManager.pluginResponseTimes;
    for (var pluginEntry in responseTimes.entries) {
      for (var responseEntry in pluginEntry.value.entries) {
        analytics.sendEvent('language_server', 'pluginRequest', parameters: {
          'pluginId': pluginEntry.key.pluginId,
          'method': responseEntry.key,
          'duration': responseEntry.value.toAnalyticsString(),
        });
      }
    }
  }

  /// Send information about the response times of server.
  void _sendServerResponseTimes() {
    for (var data in _completedRequests.values) {
      analytics.sendEvent('language_server', 'request', parameters: {
        'latency': data.latencyTimes.toAnalyticsString(),
        'method': data.method,
        'duration': data.responseTimes.toAnalyticsString(),
        for (var field in data.additionalPercentiles.entries)
          field.key: field.value.toAnalyticsString(),
        for (var field in data.additionalEnumCounts.entries)
          field.key: json.encode(field.value),
      });
    }
  }

  /// Send information about the session.
  void _sendSessionData(SessionData sessionData) {
    var endTime = DateTime.now().millisecondsSinceEpoch;
    var duration = endTime - sessionData.startTime.millisecondsSinceEpoch;
    analytics.sendEvent('language_server', 'session', parameters: {
      'flags': sessionData.commandLineArguments,
      'parameters': sessionData.initializeParams,
      'clientId': sessionData.clientId,
      'clientVersion': sessionData.clientVersion,
      'sdkVersion': sessionData.sdkVersion,
      'duration': duration.toString(),
      'plugins': _pluginData.usageCountData,
    });
  }

  void _sendSeverityAdjustments() {
    if (_severityAdjustments.isNotEmpty) {
      analytics
          .sendEvent('language_server', 'severityAdjustments', parameters: {
        'adjustmentCounts': json.encode(_severityAdjustments),
      });
    }
  }
}

extension on Either2<int, String> {
  String get asString {
    return map((value) => value.toString(), (value) => value);
  }
}
