// Copyright 2020 The Flutter Authors. 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:logging/logging.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';

class MockPlatform extends Mock implements Platform {}

class MockProcessManager extends Mock implements ProcessManager {
  @override
  Future<Process> start(
    List<Object>? command, {
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment = true,
    bool runInShell = false,
    ProcessStartMode mode = ProcessStartMode.normal,
  }) {
    return super.noSuchMethod(Invocation.method(#start, [command], {#workingDirectory: workingDirectory}),
        returnValue: Future<Process>.value(FakeProcess(0)));
  }

  @override
  ProcessResult runSync(
    List<Object> command, {
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment = true,
    bool runInShell = false,
    covariant Encoding? stdoutEncoding = systemEncoding,
    covariant Encoding? stderrEncoding = systemEncoding,
  }) {
    return super.noSuchMethod(Invocation.method(#runSync, [command]), returnValue: ProcessResult(1, 0, 'abc', 'def'));
  }

  @override
  Future<ProcessResult> run(
    List<Object> command, {
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment = true,
    bool runInShell = false,
    covariant Encoding? stdoutEncoding = systemEncoding,
    covariant Encoding? stderrEncoding = systemEncoding,
  }) {
    return super
        .noSuchMethod(Invocation.method(#run, [command]), returnValue: Future.value(ProcessResult(1, 0, 'abc', 'def')));
  }
}

class FakeProcess extends Fake implements Process {
  FakeProcess(int exitCode,
      {List<List<int>>? err = const [
        <int>[1, 2, 3]
      ],
      List<List<int>>? out = const [
        <int>[1, 2, 3]
      ]})
      : _exitCode = exitCode,
        _err = err,
        _out = out;

  int _exitCode;
  List<List<int>>? _err;
  List<List<int>>? _out;

  @override
  Future<int> get exitCode => Future.value(_exitCode);

  @override
  Stream<List<int>> get stderr => Stream.fromIterable(_err ?? <List<int>>[]);

  @override
  Stream<List<int>> get stdout => Stream.fromIterable(_out ?? <List<int>>[utf8.encode('test')]);
}

class TestLogger implements Logger {
  final String name = 'test-logger';
  String get fullName => name;
  void clearListeners() => throw UnimplementedError('Unimplemented!');
  bool isLoggable(Level value) => throw UnimplementedError('Unimplemented!');
  Level get level => throw UnimplementedError('Unimplemented!');
  set level(Level? value) => throw UnimplementedError('Unimplemented!');
  Stream<LogRecord> get onRecord => throw UnimplementedError('Unimplemented!');
  final Logger? parent = null;
  final Map<String, Logger> children = const <String, Logger>{};

  final Map<Level, List<String>> logs = <Level, List<String>>{};

  void log(Level logLevel, Object? message, [Object? error, StackTrace? stackTrace, Zone? zone]) {
    logs[logLevel] ??= <String>[];
    logs[logLevel]!.add(message.toString());
  }

  void finest(Object? message, [Object? error, StackTrace? stackTrace]) =>
      log(Level.FINEST, message, error, stackTrace);

  void finer(Object? message, [Object? error, StackTrace? stackTrace]) => log(Level.FINER, message, error, stackTrace);

  void fine(Object? message, [Object? error, StackTrace? stackTrace]) => log(Level.FINE, message, error, stackTrace);

  void config(Object? message, [Object? error, StackTrace? stackTrace]) =>
      log(Level.CONFIG, message, error, stackTrace);

  void info(Object? message, [Object? error, StackTrace? stackTrace]) => log(Level.INFO, message, error, stackTrace);

  void warning(Object? message, [Object? error, StackTrace? stackTrace]) =>
      log(Level.WARNING, message, error, stackTrace);

  void severe(Object? message, [Object? error, StackTrace? stackTrace]) =>
      log(Level.SEVERE, message, error, stackTrace);

  void shout(Object? message, [Object? error, StackTrace? stackTrace]) => log(Level.SHOUT, message, error, stackTrace);
}
