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

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/utilities/process.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:http/http.dart' as http;
import 'package:test/test.dart';

/// A [Matcher] that check that the given [Response] has an expected identifier
/// and has an error.  The error code may optionally be checked.
Matcher isResponseFailure(String id, [RequestErrorCode? code]) =>
    _IsResponseFailure(id, code);

/// A [Matcher] that check that the given [Response] has an expected identifier
/// and no error.
Matcher isResponseSuccess(String id) => _IsResponseSuccess(id);

class MockHttpClient extends http.BaseClient {
  late Future<http.Response> Function(http.BaseRequest request) sendHandler;
  int sendHandlerCalls = 0;
  bool wasClosed = false;

  @override
  void close() {
    wasClosed = true;
  }

  @override
  dynamic noSuchMethod(Invocation invocation) {
    return super.noSuchMethod(invocation);
  }

  @override
  Future<http.StreamedResponse> send(http.BaseRequest request) {
    if (wasClosed) {
      throw Exception('get() called after close()');
    }

    return sendHandler(request)
        .then((resp) => http.StreamedResponse(
            Stream.value(resp.body.codeUnits), resp.statusCode))
        .whenComplete(() => sendHandlerCalls++);
  }
}

class MockProcess implements Process {
  static int killedExitCode = -1;

  final int _pid;
  final _exitCodeCompleter = Completer<int>();
  final String _stdout, _stderr;

  MockProcess(this._pid, FutureOr<int> exitCode, this._stdout, this._stderr) {
    Future.value(exitCode).then(_exitCodeCompleter.complete);
  }

  @override
  Future<int> get exitCode => _exitCodeCompleter.future;

  @override
  int get pid => _pid;

  @override
  Stream<List<int>> get stderr => Future.value(utf8.encode(_stderr)).asStream();

  @override
  Stream<List<int>> get stdout => Future.value(utf8.encode(_stdout)).asStream();

  @override
  bool kill([ProcessSignal signal = ProcessSignal.sigterm]) {
    _exitCodeCompleter.complete(killedExitCode);
    return true;
  }

  @override
  dynamic noSuchMethod(Invocation invocation) {
    return super.noSuchMethod(invocation);
  }
}

class MockProcessRunner implements ProcessRunner {
  FutureOr<Process> Function(String executable, List<String> arguments,
          {String? dir, Map<String, String>? env}) startHandler =
      (executable, arguments, {dir, env}) => throw UnimplementedError();

  @override
  dynamic noSuchMethod(Invocation invocation) {
    return super.noSuchMethod(invocation);
  }

  @override
  Future<Process> start(
    String executable,
    List<String> arguments, {
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment = true,
    bool runInShell = false,
    ProcessStartMode mode = ProcessStartMode.normal,
  }) async {
    return await startHandler(executable, arguments,
        dir: workingDirectory, env: environment);
  }
}

class MockSource implements Source {
  @override
  final String fullName;

  MockSource({
    this.fullName = 'mocked.dart',
  });

  @override
  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);

  @override
  String toString() => fullName;
}

class StringTypedMock {
  final String? _toString;

  StringTypedMock(this._toString);

  @override
  String toString() {
    return _toString ?? super.toString();
  }
}

/// A [Matcher] that check that there are no `error` in a given [Response].
class _IsResponseFailure extends Matcher {
  final String _id;
  final RequestErrorCode? _code;

  _IsResponseFailure(this._id, this._code);

  @override
  Description describe(Description description) {
    description =
        description.add('response with identifier "$_id" and an error');
    var code = _code;
    if (code != null) {
      description = description.add(' with code ${code.name}');
    }
    return description;
  }

  @override
  Description describeMismatch(Object? item, Description mismatchDescription,
      Map matchState, bool verbose) {
    var response = item as Response;
    var id = response.id;
    var error = response.error;
    mismatchDescription.add('has identifier "$id"');
    if (error == null) {
      mismatchDescription.add(' and has no error');
    } else {
      mismatchDescription.add(' and has error code ${error.code.name}');
    }
    return mismatchDescription;
  }

  @override
  bool matches(Object? item, Map matchState) {
    var response = item as Response;
    var error = response.error;
    if (response.id != _id || error == null) {
      return false;
    }
    if (_code != null && error.code != _code) {
      return false;
    }
    return true;
  }
}

/// A [Matcher] that check that there are no `error` in a given [Response].
class _IsResponseSuccess extends Matcher {
  final String _id;

  _IsResponseSuccess(this._id);

  @override
  Description describe(Description description) {
    return description
        .addDescriptionOf('response with identifier "$_id" and without error');
  }

  @override
  Description describeMismatch(Object? item, Description mismatchDescription,
      Map matchState, bool verbose) {
    var response = item as Response?;
    if (response == null) {
      mismatchDescription.add('is null response');
    } else {
      var id = response.id;
      var error = response.error;
      mismatchDescription.add('has identifier "$id"');
      if (error != null) {
        mismatchDescription.add(' and has error $error');
      }
    }
    return mismatchDescription;
  }

  @override
  bool matches(Object? item, Map matchState) {
    var response = item as Response?;
    return response != null && response.id == _id && response.error == null;
  }
}
