// Copyright (c) 2015, 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 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:logging/logging.dart';

import 'driver.dart';
import 'input_converter.dart';

/// A [CompletionRequestOperation] tracks response time along with
/// the first and last completion notifications.
class CompletionRequestOperation extends RequestOperation {
  late Driver driver;
  late StreamSubscription<CompletionResultsParams> subscription;
  late String notificationId;
  late Stopwatch stopwatch;
  bool firstNotification = true;

  CompletionRequestOperation(
      CommonInputConverter converter, Map<String, dynamic> json)
      : super(converter, json);

  @override
  Future<void>? perform(Driver driver) {
    this.driver = driver;
    subscription = driver.onCompletionResults.listen(processNotification);
    return super.perform(driver);
  }

  void processNotification(CompletionResultsParams event) {
    if (event.id == notificationId) {
      var elapsed = stopwatch.elapsed;
      if (firstNotification) {
        firstNotification = false;
        driver.results.record('completion notification first', elapsed,
            notification: true);
      }
      if (event.isLast) {
        subscription.cancel();
        driver.results.record('completion notification last', elapsed,
            notification: true);
      }
    }
  }

  @override
  void processResult(
      String id, Map<String, Object?> result, Stopwatch stopwatch) {
    notificationId = result['id'] as String;
    this.stopwatch = stopwatch;
    super.processResult(id, result, stopwatch);
  }
}

/// An [Operation] represents an action such as sending a request to the server.
abstract class Operation {
  Future<void>? perform(Driver driver);
}

/// A [RequestOperation] sends a [JSON] request to the server.
class RequestOperation extends Operation {
  final CommonInputConverter converter;
  final Map<String, dynamic> json;

  RequestOperation(this.converter, this.json);

  @override
  Future<void>? perform(Driver driver) {
    var stopwatch = Stopwatch();
    var originalId = json['id'] as String;
    var method = json['method'] as String;
    json['clientRequestTime'] = DateTime.now().millisecondsSinceEpoch;
    driver.logger.log(Level.FINE, 'Sending request: $method\n  $json');
    stopwatch.start();

    void recordResult(bool success, result) {
      var elapsed = stopwatch.elapsed;
      driver.results.record(method, elapsed, success: success);
      driver.logger
          .log(Level.FINE, 'Response received: $method : $elapsed\n  $result');
    }

    driver.send(method, converter.asMap(json['params'])).then((result) {
      recordResult(true, result);
      processResult(originalId, result!, stopwatch);
    }).catchError((exception) {
      recordResult(false, exception);
      converter.processErrorResponse(originalId, exception);
    });
    return null;
  }

  void processResult(
      String id, Map<String, Object?> result, Stopwatch stopwatch) {
    converter.processResponseResult(id, result);
  }
}

/// A [ResponseOperation] waits for a [JSON] response from the server.
class ResponseOperation extends Operation {
  static final Duration responseTimeout = Duration(seconds: 60);
  final CommonInputConverter converter;
  final Map<String, Object?> requestJson;
  final Map<String, Object?> responseJson;
  final Completer completer = Completer();
  late Driver driver;

  ResponseOperation(this.converter, this.requestJson, this.responseJson) {
    completer.future.then(_processResult).timeout(responseTimeout);
  }

  @override
  Future<void>? perform(Driver driver) {
    this.driver = driver;
    var id = responseJson['id'] as String;
    return converter.processExpectedResponse(id, completer);
  }

  bool _equal(expectedResult, actualResult) {
    if (expectedResult is Map && actualResult is Map) {
      if (expectedResult.length == actualResult.length) {
        return expectedResult.keys.every((key) {
          return key ==
                  'fileStamp' || // fileStamp values will not be the same across runs
              _equal(expectedResult[key], actualResult[key]);
        });
      }
    } else if (expectedResult is List && actualResult is List) {
      if (expectedResult.length == actualResult.length) {
        for (var i = 0; i < expectedResult.length; ++i) {
          if (!_equal(expectedResult[i], actualResult[i])) {
            return false;
          }
        }
        return true;
      }
    }
    return expectedResult == actualResult;
  }

  /// Compare the expected and actual server response result.
  void _processResult(actualResult) {
    var expectedResult = responseJson['result'];
    if (!_equal(expectedResult, actualResult)) {
      var expectedError = responseJson['error'];
      String format(value) {
        var text = '\n$value';
        if (text.endsWith('\n')) {
          text = text.substring(0, text.length - 1);
        }
        return text.replaceAll('\n', '\n  ');
      }

      var message = 'Request:${format(requestJson)}\n'
          'expected result:${format(expectedResult)}\n'
          'expected error:${format(expectedError)}\n'
          'but received:${format(actualResult)}';
      var method = requestJson['method'] as String;
      driver.results.recordUnexpectedResults(method);
      converter.logOverlayContent();
      if (expectedError == null) {
        converter.logger.log(Level.SEVERE, message);
      } else {
        throw message;
      }
    }
  }
}

class StartServerOperation extends Operation {
  @override
  Future perform(Driver driver) {
    return driver.startServer();
  }
}

class WaitForAnalysisCompleteOperation extends Operation {
  @override
  Future perform(Driver driver) {
    var start = DateTime.now();
    driver.logger.log(Level.FINE, 'waiting for analysis to complete');
    late StreamSubscription<ServerStatusParams> subscription;
    late Timer timer;
    var completer = Completer();
    var isAnalyzing = false;
    subscription = driver.onServerStatus.listen((ServerStatusParams params) {
      var analysisStatus = params.analysis;
      if (analysisStatus != null) {
        if (analysisStatus.isAnalyzing) {
          isAnalyzing = true;
        } else {
          subscription.cancel();
          timer.cancel();
          var end = DateTime.now();
          var delta = end.difference(start);
          driver.logger.log(Level.FINE, 'analysis complete after $delta');
          completer.complete();
          driver.results.record('analysis complete', delta, notification: true);
        }
      }
    });
    timer = Timer.periodic(Duration(milliseconds: 20), (_) {
      if (!isAnalyzing) {
        // TODO (danrubel) revisit this once source change requests are implemented
        subscription.cancel();
        timer.cancel();
        driver.logger.log(Level.INFO, 'analysis never started');
        completer.complete();
        return;
      }
      // Timeout if no communication received within the last 60 seconds.
      var currentTime = driver.server.currentElapseTime;
      var lastTime = driver.server.lastCommunicationTime!;
      if (currentTime - lastTime > 60) {
        subscription.cancel();
        timer.cancel();
        var message = 'gave up waiting for analysis to complete';
        driver.logger.log(Level.WARNING, message);
        completer.completeError(message);
      }
    });
    return completer.future;
  }
}
