// Copyright 2013 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' as io;

import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_plugin_tools/src/common.dart';
import 'package:meta/meta.dart';
import 'package:platform/platform.dart';
import 'package:quiver/collection.dart';

// TODO(stuartmorgan): Eliminate this in favor of setting up a clean filesystem
// for each test, to eliminate the chance of files from one test interfering
// with another test.
FileSystem mockFileSystem = MemoryFileSystem(
    style: const LocalPlatform().isWindows
        ? FileSystemStyle.windows
        : FileSystemStyle.posix);
Directory mockPackagesDir;

/// Creates a mock packages directory in the mock file system.
///
/// If [parentDir] is set the mock packages dir will be creates as a child of
/// it. If not [mockFileSystem] will be used instead.
void initializeFakePackages({Directory parentDir}) {
  mockPackagesDir =
      (parentDir ?? mockFileSystem.currentDirectory).childDirectory('packages');
  mockPackagesDir.createSync();
}

/// Creates a plugin package with the given [name] in [packagesDirectory],
/// defaulting to [mockPackagesDir].
Directory createFakePlugin(
  String name, {
  bool withSingleExample = false,
  List<String> withExamples = const <String>[],
  List<List<String>> withExtraFiles = const <List<String>>[],
  bool isFlutter = true,
  bool isAndroidPlugin = false,
  bool isIosPlugin = false,
  bool isWebPlugin = false,
  bool isLinuxPlugin = false,
  bool isMacOsPlugin = false,
  bool isWindowsPlugin = false,
  bool includeChangeLog = false,
  bool includeVersion = false,
  String version = '0.0.1',
  String parentDirectoryName = '',
  Directory packagesDirectory,
}) {
  assert(!(withSingleExample && withExamples.isNotEmpty),
      'cannot pass withSingleExample and withExamples simultaneously');

  Directory parentDirectory = packagesDirectory ?? mockPackagesDir;
  if (parentDirectoryName != '') {
    parentDirectory = parentDirectory.childDirectory(parentDirectoryName);
  }
  final Directory pluginDirectory = parentDirectory.childDirectory(name);
  pluginDirectory.createSync(recursive: true);

  createFakePubspec(pluginDirectory,
      name: name,
      isFlutter: isFlutter,
      isAndroidPlugin: isAndroidPlugin,
      isIosPlugin: isIosPlugin,
      isWebPlugin: isWebPlugin,
      isLinuxPlugin: isLinuxPlugin,
      isMacOsPlugin: isMacOsPlugin,
      isWindowsPlugin: isWindowsPlugin,
      includeVersion: includeVersion,
      version: version);
  if (includeChangeLog) {
    createFakeCHANGELOG(pluginDirectory, '''
## 0.0.1
  * Some changes.
  ''');
  }

  if (withSingleExample) {
    final Directory exampleDir = pluginDirectory.childDirectory('example')
      ..createSync();
    createFakePubspec(exampleDir,
        name: '${name}_example',
        isFlutter: isFlutter,
        includeVersion: false,
        publishTo: 'none');
  } else if (withExamples.isNotEmpty) {
    final Directory exampleDir = pluginDirectory.childDirectory('example')
      ..createSync();
    for (final String example in withExamples) {
      final Directory currentExample = exampleDir.childDirectory(example)
        ..createSync();
      createFakePubspec(currentExample,
          name: example,
          isFlutter: isFlutter,
          includeVersion: false,
          publishTo: 'none');
    }
  }

  final FileSystem fileSystem = pluginDirectory.fileSystem;
  for (final List<String> file in withExtraFiles) {
    final List<String> newFilePath = <String>[pluginDirectory.path, ...file];
    final File newFile = fileSystem.file(fileSystem.path.joinAll(newFilePath));
    newFile.createSync(recursive: true);
  }

  return pluginDirectory;
}

void createFakeCHANGELOG(Directory parent, String texts) {
  parent.childFile('CHANGELOG.md').createSync();
  parent.childFile('CHANGELOG.md').writeAsStringSync(texts);
}

/// Creates a `pubspec.yaml` file with a flutter dependency.
void createFakePubspec(
  Directory parent, {
  String name = 'fake_package',
  bool isFlutter = true,
  bool includeVersion = false,
  bool isAndroidPlugin = false,
  bool isIosPlugin = false,
  bool isWebPlugin = false,
  bool isLinuxPlugin = false,
  bool isMacOsPlugin = false,
  bool isWindowsPlugin = false,
  String publishTo = 'http://no_pub_server.com',
  String version = '0.0.1',
}) {
  parent.childFile('pubspec.yaml').createSync();
  String yaml = '''
name: $name
flutter:
  plugin:
    platforms:
''';
  if (isAndroidPlugin) {
    yaml += '''
      android:
        package: io.flutter.plugins.fake
        pluginClass: FakePlugin
''';
  }
  if (isIosPlugin) {
    yaml += '''
      ios:
        pluginClass: FLTFakePlugin
''';
  }
  if (isWebPlugin) {
    yaml += '''
      web:
        pluginClass: FakePlugin
        fileName: ${name}_web.dart
''';
  }
  if (isLinuxPlugin) {
    yaml += '''
      linux:
        pluginClass: FakePlugin
''';
  }
  if (isMacOsPlugin) {
    yaml += '''
      macos:
        pluginClass: FakePlugin
''';
  }
  if (isWindowsPlugin) {
    yaml += '''
      windows:
        pluginClass: FakePlugin
''';
  }
  if (isFlutter) {
    yaml += '''
dependencies:
  flutter:
    sdk: flutter
''';
  }
  if (includeVersion) {
    yaml += '''
version: $version
''';
  }
  if (publishTo.isNotEmpty) {
    yaml += '''
publish_to: $publishTo # Hardcoded safeguard to prevent this from somehow being published by a broken test.
''';
  }
  parent.childFile('pubspec.yaml').writeAsStringSync(yaml);
}

/// Cleans up the mock packages directory, making it an empty directory again.
void cleanupPackages() {
  mockPackagesDir.listSync().forEach((FileSystemEntity entity) {
    entity.deleteSync(recursive: true);
  });
}

typedef _ErrorHandler = void Function(Error error);

/// Run the command [runner] with the given [args] and return
/// what was printed.
/// A custom [errorHandler] can be used to handle the runner error as desired without throwing.
Future<List<String>> runCapturingPrint(
    CommandRunner<void> runner, List<String> args, {_ErrorHandler errorHandler}) async {
  final List<String> prints = <String>[];
  final ZoneSpecification spec = ZoneSpecification(
    print: (_, __, ___, String message) {
      prints.add(message);
    },
  );
  try {
    await Zone.current
      .fork(specification: spec)
      .run<Future<void>>(() => runner.run(args));
  } on Error catch (e) {
    if (errorHandler == null) {
      rethrow;
    }
    errorHandler(e);
  }

  return prints;
}

/// A mock [ProcessRunner] which records process calls.
class RecordingProcessRunner extends ProcessRunner {
  io.Process processToReturn;
  final List<ProcessCall> recordedCalls = <ProcessCall>[];

  /// Populate for [io.ProcessResult] to use a String [stdout] instead of a [List] of [int].
  String resultStdout;

  /// Populate for [io.ProcessResult] to use a String [stderr] instead of a [List] of [int].
  String resultStderr;

  @override
  Future<int> runAndStream(
    String executable,
    List<String> args, {
    Directory workingDir,
    bool exitOnError = false,
  }) async {
    recordedCalls.add(ProcessCall(executable, args, workingDir?.path));
    return Future<int>.value(
        processToReturn == null ? 0 : await processToReturn.exitCode);
  }

  /// Returns [io.ProcessResult] created from [processToReturn], [resultStdout], and [resultStderr].
  @override
  Future<io.ProcessResult> run(
    String executable,
    List<String> args, {
    Directory workingDir,
    bool exitOnError = false,
    bool logOnError = false,
    Encoding stdoutEncoding = io.systemEncoding,
    Encoding stderrEncoding = io.systemEncoding,
  }) async {
    recordedCalls.add(ProcessCall(executable, args, workingDir?.path));
    io.ProcessResult result;

    if (processToReturn != null) {
      result = io.ProcessResult(
          processToReturn.pid,
          await processToReturn.exitCode,
          resultStdout ?? processToReturn.stdout,
          resultStderr ?? processToReturn.stderr);
    }
    return Future<io.ProcessResult>.value(result);
  }

  @override
  Future<io.Process> start(String executable, List<String> args,
      {Directory workingDirectory}) async {
    recordedCalls.add(ProcessCall(executable, args, workingDirectory?.path));
    return Future<io.Process>.value(processToReturn);
  }
}

/// A recorded process call.
@immutable
class ProcessCall {
  const ProcessCall(this.executable, this.args, this.workingDir);

  /// The executable that was called.
  final String executable;

  /// The arguments passed to [executable] in the call.
  final List<String> args;

  /// The working directory this process was called from.
  final String workingDir;

  @override
  bool operator ==(dynamic other) {
    return other is ProcessCall &&
        executable == other.executable &&
        listsEqual(args, other.args) &&
        workingDir == other.workingDir;
  }

  @override
  int get hashCode =>
      executable?.hashCode ??
      0 ^ args?.hashCode ??
      0 ^ workingDir?.hashCode ??
      0;

  @override
  String toString() {
    final List<String> command = <String>[executable, ...args];
    return '"${command.join(' ')}" in $workingDir';
  }
}
