// Copyright (c) 2020, 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 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';

import '../command.dart';
import '../entrypoint.dart';
import '../io.dart';
import '../log.dart' as log;
import '../package.dart';
import '../pubspec.dart';
import '../solver.dart';

/// Handles the `remove` pub command. Removes dependencies from `pubspec.yaml`,
/// and performs an operation similar to `pub get`. Unlike `pub add`, this
/// command supports the removal of multiple dependencies.
class RemoveCommand extends PubCommand {
  @override
  String get name => 'remove';
  @override
  String get description => '''
Removes dependencies from `pubspec.yaml`.

Invoking `dart pub remove foo bar` will remove `foo` and `bar` from either
`dependencies` or `dev_dependencies` in `pubspec.yaml`.

To remove a dependency override of a package prefix the package name with
'override:'.
''';

  @override
  String get argumentsDescription => '<package1> [<package2>...]';
  @override
  String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-remove';
  @override
  bool get isOffline => argResults['offline'];

  bool get isDryRun => argResults['dry-run'];

  RemoveCommand() {
    argParser.addFlag(
      'offline',
      help: 'Use cached packages instead of accessing the network.',
    );

    argParser.addFlag(
      'dry-run',
      abbr: 'n',
      negatable: false,
      help: "Report what dependencies would change but don't change any.",
    );

    argParser.addFlag(
      'precompile',
      help: 'Precompile executables in immediate dependencies.',
    );

    argParser.addFlag(
      'example',
      help: 'Also update dependencies in `example/` (if it exists).',
      hide: true,
    );

    argParser.addOption(
      'directory',
      abbr: 'C',
      help: 'Run this in the directory <dir>.',
      valueHelp: 'dir',
    );
  }

  @override
  Future<void> runProtected() async {
    if (argResults.rest.isEmpty) {
      usageException('Must specify a package to be removed.');
    }

    final targets = Set<String>.from(argResults.rest).map((descriptor) {
      final isOverride = descriptor.startsWith('override:');
      final name =
          isOverride ? descriptor.substring('override:'.length) : descriptor;
      return _PackageRemoval(name, removeFromOverride: isOverride);
    });

    if (isDryRun) {
      final rootPubspec = entrypoint.root.pubspec;
      final newPubspec = _removePackagesFromPubspec(rootPubspec, targets);
      final newRoot = Package.inMemory(newPubspec);

      await Entrypoint.inMemory(newRoot, cache, lockFile: entrypoint.lockFile)
          .acquireDependencies(
        SolveType.get,
        precompile: argResults['precompile'],
        dryRun: true,
        analytics: null,
      );
    } else {
      /// Update the pubspec.
      _writeRemovalToPubspec(targets);

      /// Create a new [Entrypoint] since we have to reprocess the updated
      /// pubspec file.
      final updatedEntrypoint = Entrypoint(directory, cache);
      await updatedEntrypoint.acquireDependencies(
        SolveType.get,
        precompile: argResults['precompile'],
        analytics: analytics,
      );

      var example = entrypoint.example;
      if (argResults['example'] && example != null) {
        await example.acquireDependencies(
          SolveType.get,
          precompile: argResults['precompile'],
          summaryOnly: true,
          analytics: analytics,
        );
      }
    }
  }

  Pubspec _removePackagesFromPubspec(
    Pubspec original,
    Iterable<_PackageRemoval> packages,
  ) {
    final dependencies = {...original.dependencies};
    final devDependencies = {...original.devDependencies};
    final overrides = {...original.dependencyOverrides};

    for (final package in packages) {
      if (package.removeFromOverride) {
        overrides.remove(package.name);
      } else {
        dependencies.remove(package.name);
        devDependencies.remove(package.name);
      }
    }
    return Pubspec(
      original.name,
      version: original.version,
      sdkConstraints: original.sdkConstraints,
      dependencies: dependencies.values,
      devDependencies: devDependencies.values,
      dependencyOverrides: overrides.values,
    );
  }

  /// Writes the changes to the pubspec file
  void _writeRemovalToPubspec(Iterable<_PackageRemoval> packages) {
    ArgumentError.checkNotNull(packages, 'packages');

    final yamlEditor = YamlEditor(readTextFile(entrypoint.pubspecPath));

    for (final package in packages) {
      final dependencyKeys = package.removeFromOverride
          ? ['dependency_overrides']
          : ['dependencies', 'dev_dependencies'];
      var found = false;
      final name = package.name;

      /// There may be packages where the dependency is declared both in
      /// dependencies and dev_dependencies - remove it from both in that case.
      for (final dependencyKey in dependencyKeys) {
        final dependenciesNode = yamlEditor
            .parseAt([dependencyKey], orElse: () => YamlScalar.wrap(null));

        if (dependenciesNode is YamlMap && dependenciesNode.containsKey(name)) {
          yamlEditor.remove([dependencyKey, name]);
          found = true;
          // Check if the dependencies or dev_dependencies map is now empty
          // If it is empty, remove the key as well
          if ((yamlEditor.parseAt([dependencyKey]) as YamlMap).isEmpty) {
            yamlEditor.remove([dependencyKey]);
          }
        }
      }
      if (!found) {
        log.warning(
          'Package "$name" was not found in ${entrypoint.pubspecPath}!',
        );
      }
    }

    /// Windows line endings are already handled by [yamlEditor]
    writeTextFile(entrypoint.pubspecPath, yamlEditor.toString());
  }
}

class _PackageRemoval {
  final String name;
  final bool removeFromOverride;
  _PackageRemoval(this.name, {required this.removeFromOverride});
}
