// 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'
    show newLocation_fromElement, newLocation_fromMatch;
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/rename.dart';
import 'package:analysis_server/src/services/search/element_visitors.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/utilities/flutter.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart' show Identifier;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/java_core.dart';

/// Checks if creating a top-level function with the given [name] in [library]
/// will cause any conflicts.
Future<RefactoringStatus> validateCreateFunction(
    SearchEngine searchEngine, LibraryElement library, String name) {
  return _CreateUnitMemberValidator(
          searchEngine, library, ElementKind.FUNCTION, name)
      .validate();
}

/// Checks if creating a top-level function with the given [name] in [element]
/// will cause any conflicts.
Future<RefactoringStatus> validateRenameTopLevel(
    SearchEngine searchEngine, Element element, String name) {
  return _RenameUnitMemberValidator(searchEngine, element, name).validate();
}

/// A [Refactoring] for renaming compilation unit member [Element]s.
class RenameUnitMemberRefactoringImpl extends RenameRefactoringImpl {
  final ResolvedUnitResult resolvedUnit;

  /// If the [element] is a Flutter `StatefulWidget` declaration, this is the
  /// corresponding `State` declaration.
  ClassElement? _flutterWidgetState;

  /// If [_flutterWidgetState] is set, this is the new name of it.
  String? _flutterWidgetStateNewName;

  RenameUnitMemberRefactoringImpl(
      RefactoringWorkspace workspace, this.resolvedUnit, Element element)
      : super(workspace, element);

  @override
  String get refactoringName {
    if (element is FunctionElement) {
      return 'Rename Top-Level Function';
    }
    if (element is TopLevelVariableElement) {
      return 'Rename Top-Level Variable';
    }
    if (element is TypeAliasElement) {
      return 'Rename Type Alias';
    }
    return 'Rename Class';
  }

  @override
  Future<RefactoringStatus> checkFinalConditions() async {
    var status = await validateRenameTopLevel(searchEngine, element, newName);
    final flutterWidgetState = _flutterWidgetState;
    final flutterWidgetStateNewName = _flutterWidgetStateNewName;
    if (flutterWidgetState != null && flutterWidgetStateNewName != null) {
      _updateFlutterWidgetStateName();
      status.addStatus(
        await validateRenameTopLevel(
          searchEngine,
          flutterWidgetState,
          flutterWidgetStateNewName,
        ),
      );
    }
    return status;
  }

  @override
  Future<RefactoringStatus> checkInitialConditions() {
    _findFlutterStateClass();
    return super.checkInitialConditions();
  }

  @override
  RefactoringStatus checkNewName() {
    var result = super.checkNewName();
    if (element is TopLevelVariableElement) {
      result.addStatus(validateVariableName(newName));
    }
    if (element is FunctionElement) {
      result.addStatus(validateFunctionName(newName));
    }
    if (element is TypeAliasElement) {
      result.addStatus(validateTypeAliasName(newName));
    }
    if (element is ClassElement) {
      result.addStatus(validateClassName(newName));
    }
    return result;
  }

  @override
  Future<void> fillChange() async {
    // prepare elements
    var elements = <Element>[];
    if (element is PropertyInducingElement && element.isSynthetic) {
      var property = element as PropertyInducingElement;
      var getter = property.getter;
      var setter = property.setter;
      if (getter != null) {
        elements.add(getter);
      }
      if (setter != null) {
        elements.add(setter);
      }
    } else {
      elements.add(element);
    }

    // Rename each element and references to it.
    var processor = RenameProcessor(workspace, change, newName);
    for (var element in elements) {
      await processor.renameElement(element);
    }

    // If a StatefulWidget is being renamed, rename also its State.
    final flutterWidgetState = _flutterWidgetState;
    if (flutterWidgetState != null) {
      _updateFlutterWidgetStateName();
      await RenameProcessor(
        workspace,
        change,
        _flutterWidgetStateNewName!,
      ).renameElement(flutterWidgetState);
    }
  }

  void _findFlutterStateClass() {
    if (Flutter.instance.isStatefulWidgetDeclaration(element)) {
      var oldStateName = oldName + 'State';
      var library = element.library!;
      _flutterWidgetState =
          library.getType(oldStateName) ?? library.getType('_' + oldStateName);
    }
  }

  void _updateFlutterWidgetStateName() {
    final flutterWidgetState = _flutterWidgetState;
    if (flutterWidgetState != null) {
      var flutterWidgetStateNewName = newName + 'State';
      // If the State was private, ensure that it stays private.
      if (flutterWidgetState.name.startsWith('_') &&
          !flutterWidgetStateNewName.startsWith('_')) {
        flutterWidgetStateNewName = '_' + flutterWidgetStateNewName;
      }
      _flutterWidgetStateNewName = flutterWidgetStateNewName;
    }
  }
}

/// The base class for the create and rename validators.
class _BaseUnitMemberValidator {
  final SearchEngine searchEngine;
  final LibraryElement library;
  final ElementKind elementKind;
  final String name;

  final RefactoringStatus result = RefactoringStatus();

  _BaseUnitMemberValidator(
      this.searchEngine, this.library, this.elementKind, this.name);

  /// Returns `true` if [element] is visible at the given [SearchMatch].
  bool _isVisibleAt(Element element, SearchMatch at) {
    var atLibrary = at.element.library!;
    // may be the same library
    if (library == atLibrary) {
      return true;
    }
    // check imports
    for (var importElement in atLibrary.imports) {
      // ignore if imported with prefix
      if (importElement.prefix != null) {
        continue;
      }
      // check imported elements
      if (getImportNamespace(importElement).containsValue(element)) {
        return true;
      }
    }
    // no, it is not visible
    return false;
  }

  /// Validates if an element with the [name] will conflict with another
  /// top-level [Element] in the same library.
  void _validateWillConflict() {
    visitLibraryTopLevelElements(library, (element) {
      if (hasDisplayName(element, name)) {
        var message = format("Library already declares {0} with name '{1}'.",
            getElementKindName(element), name);
        result.addError(message, newLocation_fromElement(element));
      }
    });
  }

  /// Validates if renamed [element] will shadow any [Element] named [name].
  Future _validateWillShadow(Element? element) async {
    var declarations = await searchEngine.searchMemberDeclarations(name);
    for (var declaration in declarations) {
      var member = declaration.element;
      var declaringClass = member.enclosingElement as ClassElement;
      var memberReferences = await searchEngine.searchReferences(member);
      for (var memberReference in memberReferences) {
        var refElement = memberReference.element;
        // cannot be shadowed if qualified
        if (memberReference.isQualified) {
          continue;
        }
        // cannot be shadowed if declared in the same class as reference
        var refClass = refElement.thisOrAncestorOfType<ClassElement>();
        if (refClass == declaringClass) {
          continue;
        }
        // ignore if not visible
        if (element != null && !_isVisibleAt(element, memberReference)) {
          continue;
        }
        // OK, reference will be shadowed be the element being renamed
        var message = format(
            element != null
                ? "Renamed {0} will shadow {1} '{2}'."
                : "Created {0} will shadow {1} '{2}'.",
            elementKind.displayName,
            getElementKindName(member),
            getElementQualifiedName(member));
        result.addError(message, newLocation_fromMatch(memberReference));
      }
    }
  }
}

/// Helper to check if the created element will cause any conflicts.
class _CreateUnitMemberValidator extends _BaseUnitMemberValidator {
  _CreateUnitMemberValidator(
    SearchEngine searchEngine,
    LibraryElement library,
    ElementKind elementKind,
    String name,
  ) : super(searchEngine, library, elementKind, name);

  Future<RefactoringStatus> validate() async {
    _validateWillConflict();
    await _validateWillShadow(null);
    return result;
  }
}

/// Helper to check if the renamed element will cause any conflicts.
class _RenameUnitMemberValidator extends _BaseUnitMemberValidator {
  final Element element;
  List<SearchMatch> references = <SearchMatch>[];

  _RenameUnitMemberValidator(
    SearchEngine searchEngine,
    this.element,
    String name,
  ) : super(searchEngine, element.library!, element.kind, name);

  Future<RefactoringStatus> validate() async {
    _validateWillConflict();
    references = await searchEngine.searchReferences(element);
    _validateWillBeInvisible();
    _validateWillBeShadowed();
    await _validateWillShadow(element);
    return result;
  }

  /// Validates if any usage of [element] renamed to [name] will be invisible.
  void _validateWillBeInvisible() {
    if (!Identifier.isPrivateName(name)) {
      return;
    }
    for (var reference in references) {
      var refElement = reference.element;
      var refLibrary = refElement.library!;
      if (refLibrary != library) {
        var message = format("Renamed {0} will be invisible in '{1}'.",
            getElementKindName(element), getElementQualifiedName(refLibrary));
        result.addError(message, newLocation_fromMatch(reference));
      }
    }
  }

  /// Validates if any usage of [element] renamed to [name] will be shadowed.
  void _validateWillBeShadowed() {
    for (var reference in references) {
      var refElement = reference.element;
      var refClass = refElement.thisOrAncestorOfType<ClassElement>();
      if (refClass != null) {
        visitChildren(refClass, (shadow) {
          if (hasDisplayName(shadow, name)) {
            var message = format(
                "Reference to renamed {0} will be shadowed by {1} '{2}'.",
                getElementKindName(element),
                getElementKindName(shadow),
                getElementQualifiedName(shadow));
            result.addError(message, newLocation_fromElement(shadow));
          }
          return false;
        });
      }
    }
  }
}
