// 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 'dart:io';

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/channel/byte_stream_channel.dart';

/// Helper for tracking request handling statistics.
///
/// All [DateTime] are local, not UTC.
class RequestStatisticsHelper {
  final String _sdkVersion = Platform.version.split(' ').first;

  final Map<String, _RequestStatistics> _statisticsMap = {};

  /// The [StringSink] to which performance logger should copy its output.
  late final _ServerLogStringSink _perfLoggerStringSink =
      _ServerLogStringSink(this);

  /// The channel to send 'server.log' notifications to.
  ByteStreamServerChannel? _serverChannel;

  /// Is `true` if the client subscribed for "server.log" notification.
  bool _isNotificationSubscribed = false;

  RequestStatisticsHelper();

  /// Set whether the client subscribed for "server.log" notification.
  set isNotificationSubscribed(bool value) {
    _isNotificationSubscribed = value;
  }

  /// The [StringSink] to which performance logger should copy its output.
  StringSink get perfLoggerStringSink => _perfLoggerStringSink;

  /// The channel sets itself using this method.
  set serverChannel(ByteStreamServerChannel serverChannel) {
    _serverChannel = serverChannel;
  }

  /// Add a time marker item to the data associated with the [request].
  void addItemTimeNow(Request request, String name) {
    var id = request.id;
    var stat = _statisticsMap[id];
    if (stat != null) {
      stat.items.add(
        _RequestStatisticsItem(
          name,
          timeValue: DateTime.now(),
        ),
      );
    }
  }

  /// The new [request] was received. Record the time when the client sent it,
  /// and the time when the server received it (now).
  void addRequest(Request request) {
    _logRequest(request);

    var id = request.id;

    var clientRequestMilliseconds = request.clientRequestTime;
    if (clientRequestMilliseconds == null) {
      return;
    }
    var clientRequestTime = DateTime.fromMillisecondsSinceEpoch(
      clientRequestMilliseconds,
    );

    var serverRequestTime = DateTime.now();

    _statisticsMap[id] = _RequestStatistics(
      id,
      request.method,
      clientRequestTime,
      serverRequestTime,
    );
  }

  /// The server finished processing a request, and sends the [response].
  /// Record the time when the response is about to be sent to the client.
  void addResponse(Response response) {
    if (!_isNotificationSubscribed) return;
    if (_serverChannel == null) return;

    var id = response.id;
    var stat = _statisticsMap.remove(id);
    if (stat != null) {
      var responseTime = DateTime.now();
      _sendLogEntry(ServerLogEntryKind.RESPONSE, stat.toJson(responseTime));
    }
  }

  void logNotification(Notification notification) {
    if (!_isNotificationSubscribed) return;
    if (_serverChannel == null) return;

    var event = notification.event;

    // Don't log large and often notifications.
    if (event == 'analysis.errors' ||
        event == 'completion.availableSuggestions') {
      return;
    }

    var params = notification.params;
    if (params == null) {
      return;
    }

    var map = <String, Object>{
      'event': event,
    };

    if (event == 'analysis.highlights' ||
        event == 'analysis.implemented' ||
        event == 'analysis.navigation' ||
        event == 'analysis.outline' ||
        event == 'analysis.overrides') {
      map['file'] = params['file'] as String;
    }

    if (event == 'server.status') {
      var analysis = params['analysis'];
      if (analysis is Map<String, Object?>) {
        map['isAnalyzing'] = analysis['isAnalyzing'] as bool;
      }
    }

    _sendLogEntry(ServerLogEntryKind.NOTIFICATION, map);
  }

  void _logRequest(Request request) {
    if (!_isNotificationSubscribed) return;
    if (_serverChannel == null) return;

    var method = request.method;
    var map = <String, Object>{
      'id': request.id,
      'method': method,
    };

    {
      var clientRequestTime = request.clientRequestTime;
      if (clientRequestTime != null) {
        map['clientRequestTime'] = clientRequestTime;
      }
    }

    if (method == 'analysis.updateContent') {
      var filesMap = request.params['files'];
      if (filesMap is Map<String, Object>) {
        map['files'] = filesMap.keys.toList();
      }
    } else {
      map = request.toJson();
    }

    _sendLogEntry(ServerLogEntryKind.REQUEST, map);
  }

  void _sendLogEntry(ServerLogEntryKind kind, Object data) {
    if (!_isNotificationSubscribed) return;

    var serverChannel = _serverChannel;
    if (serverChannel == null) return;

    serverChannel.sendNotification(
      Notification(
        'server.log',
        <String, Object>{
          'time': DateTime.now().millisecondsSinceEpoch,
          'kind': kind.toJson(
            clientUriConverter: null,
          ),
          'data': data,
          'sdkVersion': _sdkVersion,
        },
      ),
    );
  }
}

class _RequestStatistics {
  final String id;
  final String method;
  final DateTime clientRequestTime;
  final DateTime serverRequestTime;
  final List<_RequestStatisticsItem> items = [];

  _RequestStatistics(
    this.id,
    this.method,
    this.clientRequestTime,
    this.serverRequestTime,
  );

  Map<String, Object> toJson(DateTime responseTime) {
    var map = {
      'id': id,
      'method': method,
      'clientRequestTime': clientRequestTime.millisecondsSinceEpoch,
      'serverRequestTime': serverRequestTime.millisecondsSinceEpoch,
      'responseTime': responseTime.millisecondsSinceEpoch,
    };
    if (items.isNotEmpty) {
      map['items'] = items.map((item) => item.toJson()).toList();
    }
    return map;
  }
}

class _RequestStatisticsItem {
  final String name;
  final DateTime? timeValue;

  _RequestStatisticsItem(this.name, {this.timeValue});

  Map<String, Object> toJson() {
    var timeValue = this.timeValue;
    if (timeValue != null) {
      return {
        'name': name,
        'timeValue': timeValue.millisecondsSinceEpoch,
      };
    }
    throw StateError('Unknown value: $name');
  }
}

class _ServerLogStringSink implements StringSink {
  final RequestStatisticsHelper helper;

  _ServerLogStringSink(this.helper);

  @override
  void write(Object? obj) {
    throw UnimplementedError();
  }

  @override
  void writeAll(Iterable<Object?> objects, [String separator = '']) {
    throw UnimplementedError();
  }

  @override
  void writeCharCode(int charCode) {
    throw UnimplementedError();
  }

  @override
  void writeln([Object? obj = '']) {
    helper._sendLogEntry(ServerLogEntryKind.RAW, '$obj');
  }
}
