// 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 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/refactoring/rename.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';

/// A [Refactoring] for renaming [ConstructorElement]s.
class RenameConstructorRefactoringImpl extends RenameRefactoringImpl {
  final AnalysisSession session;

  RenameConstructorRefactoringImpl(
      RefactoringWorkspace workspace, this.session, ConstructorElement element)
      : super(workspace, element);

  @override
  ConstructorElement get element => super.element as ConstructorElement;

  @override
  String get refactoringName {
    return 'Rename Constructor';
  }

  @override
  Future<RefactoringStatus> checkFinalConditions() {
    var result = RefactoringStatus();
    return Future.value(result);
  }

  @override
  RefactoringStatus checkNewName() {
    var result = super.checkNewName();
    result.addStatus(validateConstructorName(newName));
    _analyzePossibleConflicts(result);
    return result;
  }

  @override
  Future<void> fillChange() async {
    // prepare references
    var matches = await searchEngine.searchReferences(element);
    var references = getSourceReferences(matches);
    // update references
    for (var reference in references) {
      String replacement;
      if (newName.isNotEmpty) {
        replacement = '.$newName';
      } else {
        replacement = reference.isConstructorTearOff ? '.new' : '';
      }
      if (reference.isInvocationByEnumConstantWithoutArguments) {
        replacement += '()';
      }
      reference.addEdit(change, replacement);
    }
    // Update the declaration.
    if (element.isSynthetic) {
      await _replaceSynthetic();
    } else {
      doSourceChange_addSourceEdit(
        change,
        element.source,
        newSourceEdit_range(
          _declarationNameRange(),
          newName.isNotEmpty ? '.$newName' : '',
        ),
      );
    }
  }

  void _analyzePossibleConflicts(RefactoringStatus result) {
    var parentClass = element.enclosingElement;
    // Check if the "newName" is the name of the enclosing class.
    if (parentClass.name == newName) {
      result.addError('The constructor should not have the same name '
          'as the name of the enclosing class.');
    }
    // check if there are members with "newName" in the same ClassElement
    for (var newNameMember in getChildren(parentClass, newName)) {
      var message = format("Class '{0}' already declares {1} with name '{2}'.",
          parentClass.displayName, getElementKindName(newNameMember), newName);
      result.addError(message, newLocation_fromElement(newNameMember));
    }
  }

  SourceRange _declarationNameRange() {
    var offset = element.periodOffset;
    var nameEnd = element.nameEnd!;
    if (offset != null) {
      return range.startOffsetEndOffset(offset, nameEnd);
    } else {
      return SourceRange(nameEnd, 0);
    }
  }

  Future<void> _replaceSynthetic() async {
    var classElement = element.enclosingElement;

    var result = await AnalysisSessionHelper(session)
        .getElementDeclaration(classElement);
    if (result == null) {
      return;
    }

    var resolvedUnit = result.resolvedUnit;
    if (resolvedUnit == null) {
      return;
    }

    var node = result.node;
    if (node is ClassDeclaration) {
      var utils = CorrectionUtils(resolvedUnit);
      var location = utils.prepareNewConstructorLocation(session, node);
      if (location == null) {
        return;
      }

      var header = '${classElement.name}.$newName();';
      doSourceChange_addElementEdit(
        change,
        classElement,
        SourceEdit(
          location.offset,
          0,
          location.prefix + header + location.suffix,
        ),
      );
    } else if (node is EnumDeclaration) {
      var utils = CorrectionUtils(resolvedUnit);
      var location = utils.prepareEnumNewConstructorLocation(node);
      if (location == null) {
        return;
      }

      var header = 'const ${classElement.name}.$newName();';
      doSourceChange_addElementEdit(
        change,
        classElement,
        SourceEdit(
          location.offset,
          0,
          location.prefix + header + location.suffix,
        ),
      );
    }
  }
}
