// Copyright (c) 2022, 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:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/src/services/refactoring/framework/refactoring_producer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

/// An object that can compute a refactoring in a Dart file.
class MoveTopLevelToFile extends RefactoringProducer {
  /// Return the name used for this command when communicating with the client.
  static const String commandName = 'move_top_level_to_file';

  @override
  late String title;

  /// The default path of the file to which the declaration should be moved.
  late String defaultFilePath;

  /// Initialize a newly created refactoring producer to use the given
  /// [context].
  MoveTopLevelToFile(super.context);

  @override
  List<CommandParameter> get parameters => [
        CommandParameter(
          label: 'Move to:',
          type: CommandParameterType.filePath,
          defaultValue: defaultFilePath,
        ),
      ];

  /// Return the member to be moved. As a side-effect, initialize the [title]
  /// and [defaultFilePath].
  _MemberToMove? get _memberToMove {
    // TODO(brianwilkerson) Extend this to support the selection of multiple
    //  top-level declarations by returning a list of the members to be moved.
    var node = selectedNode;
    // TODO(brianwilkerson) If the caret is at the end of the name and before
    //  the parameter list, then the `node` is the parameter list. This code
    //  doesn't handle that case yet.
    if (node is VariableDeclaration) {
      var declaration = node.parent?.parent;
      if (declaration is TopLevelVariableDeclaration &&
          declaration.variables.variables.length == 1 &&
          selectionIsInToken(node.name)) {
        return _memberFor(declaration, node.name.lexeme);
      }
    }
    if (node is! CompilationUnitMember) {
      return null;
    }
    String name;
    if (node is ClassDeclaration && selectionIsInToken(node.name)) {
      name = node.name.lexeme;
    } else if (node is EnumDeclaration && selectionIsInToken(node.name)) {
      name = node.name.lexeme;
    } else if (node is ExtensionDeclaration && selectionIsInToken(node.name)) {
      name = node.name!.lexeme;
    } else if (node is FunctionDeclaration &&
        node.parent is CompilationUnit &&
        selectionIsInToken(node.name)) {
      name = node.name.lexeme;
    } else if (node is MixinDeclaration && selectionIsInToken(node.name)) {
      name = node.name.lexeme;
    } else if (node is TypeAlias && selectionIsInToken(node.name)) {
      name = node.name.lexeme;
    } else {
      return null;
    }
    return _memberFor(node, name);
  }

  @override
  Future<void> compute(
      List<String> commandArguments, ChangeBuilder builder) async {
    var member = _memberToMove;
    if (member == null) {
      return;
    }
    var sourcePath = member.containingFile;
    var destinationFilePath = commandArguments[0];
    var destinationUri = result.session.uriConverter
        .pathToUri(destinationFilePath, containingPath: sourcePath);
    if (destinationUri == null) {
      return;
    }
    await builder.addDartFileEdit(destinationFilePath, (builder) {
      // TODO(brianwilkerson) Copy the file header to the new file.
      // TODO(brianwilkerson) Use `ImportedElementsComputer` to add imports
      //  required by the newly copied code. Better yet, combine that with the
      //  import analysis used to find unused and unnecessary imports so that we
      //  can also remove any unused or unnecessary imports from the source
      //  library.
      // TODO(dantup): Ensure the range inserted and deleted match (allowing for
      //  whitespace), including handling of leading/trailing comments etc.
      builder.addInsertion(0, (builder) {
        builder.writeln(utils.getNodeText(member.node));
      });
    });
    await builder.addDartFileEdit(sourcePath, (builder) {
      // TODO(brianwilkerson) Only add an import for the new file if the
      //  remaining code references the moved code.
      // builder.importLibrary(destinationUri);
      builder.addDeletion(range.deletionRange(member.node));
    });
    // TODO(brianwilkerson) Find references to the moved declaration(s) outside
    //  the source library and update the imports in those files.
  }

  @override
  bool isAvailable() => supportsFileCreation && _memberToMove != null;

  /// Computes a filename for a given class name (convert from PascalCase to
  /// snake_case).
  // TODO(brianwilkerson) Copied from handler_rename.dart. Move this code to a
  //  common location, preferably as an extension on `String`.
  String _fileNameForClassName(String className) {
    final fileName = className
        .replaceAllMapped(RegExp('[A-Z]'),
            (match) => match.start == 0 ? match[0]! : '_${match[0]}')
        .toLowerCase();
    return '$fileName.dart';
  }

  _MemberToMove? _memberFor(CompilationUnitMember declaration, String name) {
    // TODO(brianwilkeson) Handle other top-level members, including
    //  augmentations.
    var unitPath = result.unit.declaredElement?.source.fullName;
    if (unitPath == null) {
      return null;
    }
    var context = result.session.resourceProvider.pathContext;

    title = "Move '$name' to file";
    defaultFilePath =
        context.join(context.dirname(unitPath), _fileNameForClassName(name));
    return _MemberToMove(unitPath, declaration, name);
  }
}

/// Information about the member to be moved.
class _MemberToMove {
  /// The absolute and normalized path of the file containing the member.
  final String containingFile;

  /// The member to be moved.
  final CompilationUnitMember node;

  /// The name of the member.
  final String name;

  /// Initialize a newly created instance representing the [member] with the
  /// given [name].
  _MemberToMove(this.containingFile, this.node, this.name);
}
