// 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.

library services.src.refactoring.rename;

import 'dart:async';

import 'package:analysis_server/src/protocol_server.dart' hide Element;
import 'package:analysis_server/src/services/correction/source_range.dart';
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/refactoring.dart';
import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:path/path.dart' as pathos;

/**
 * Returns `true` if two given [Element]s are [LocalElement]s and have
 * intersecting with visibility ranges.
 */
bool haveIntersectingRanges(LocalElement localElement, Element element) {
  if (element is! LocalElement) {
    return false;
  }
  LocalElement localElement2 = element as LocalElement;
  Source localSource = localElement.source;
  Source localSource2 = localElement2.source;
  SourceRange localRange = localElement.visibleRange;
  SourceRange localRange2 = localElement2.visibleRange;
  return localSource2 == localSource &&
      localRange != null &&
      localRange2 != null &&
      localRange2.intersects(localRange);
}

/**
 * Checks if [element] is defined in the library containing [source].
 */
bool isDefinedInLibrary(
    Element element, AnalysisContext context, Source source) {
  // should be the same AnalysisContext
  if (!isInContext(element, context)) {
    return false;
  }
  // private elements are visible only in their library
  List<Source> librarySourcesOfSource = context.getLibrariesContaining(source);
  Source librarySourceOfElement = element.library.source;
  return librarySourcesOfSource.contains(librarySourceOfElement);
}

bool isElementInPubCache(Element element) {
  Source source = element.source;
  String path = source.fullName;
  return isPathInPubCache(path);
}

bool isElementInSdkOrPubCache(Element element) {
  Source source = element.source;
  String path = source.fullName;
  return source.isInSystemLibrary || isPathInPubCache(path);
}

/**
 * Checks if the given [Element] is in the given [AnalysisContext].
 */
bool isInContext(Element element, AnalysisContext context) {
  return element.context == context;
}

bool isPathInPubCache(String path) {
  List<String> parts = pathos.split(path);
  if (parts.contains('.pub-cache')) {
    return true;
  }
  for (int i = 0; i < parts.length - 1; i++) {
    if (parts[i] == 'Pub' && parts[i + 1] == 'Cache') {
      return true;
    }
    if (parts[i] == 'third_party' &&
        (parts[i + 1] == 'pkg' || parts[i + 1] == 'pkg_tested')) {
      return true;
    }
  }
  return false;
}

/**
 * Checks if the given unqualified [SearchMatch] intersects with visibility
 * range of [localElement].
 */
bool isReferenceInLocalRange(LocalElement localElement, SearchMatch reference) {
  if (reference.isQualified) {
    return false;
  }
  Source localSource = localElement.source;
  Source referenceSource = reference.element.source;
  SourceRange localRange = localElement.visibleRange;
  SourceRange referenceRange = reference.sourceRange;
  return referenceSource == localSource &&
      referenceRange.intersects(localRange);
}

/**
 * Checks if [element] is visible in the library containing [source].
 */
bool isVisibleInLibrary(
    Element element, AnalysisContext context, Source source) {
  // should be the same AnalysisContext
  if (!isInContext(element, context)) {
    return false;
  }
  // public elements are always visible
  if (element.isPublic) {
    return true;
  }
  // private elements are visible only in their library
  return isDefinedInLibrary(element, context, source);
}

/**
 * An abstract implementation of [RenameRefactoring].
 */
abstract class RenameRefactoringImpl extends RefactoringImpl
    implements RenameRefactoring {
  final SearchEngine searchEngine;
  final Element element;
  final AnalysisContext context;
  final String elementKindName;
  final String oldName;

  SourceChange change;

  String newName;

  RenameRefactoringImpl(SearchEngine searchEngine, Element element)
      : searchEngine = searchEngine,
        element = element,
        context = element.context,
        elementKindName = element.kind.displayName,
        oldName = _getDisplayName(element);

  /**
   * Adds a [SourceEdit] to update [element] name to [change].
   */
  void addDeclarationEdit(Element element) {
    if (element != null) {
      SourceRange range = rangeElementName(element);
      SourceEdit edit = newSourceEdit_range(range, newName);
      doSourceChange_addElementEdit(change, element, edit);
    }
  }

  /**
   * Adds [SourceEdit]s to update [matches] to [change].
   */
  void addReferenceEdits(List<SearchMatch> matches) {
    List<SourceReference> references = getSourceReferences(matches);
    for (SourceReference reference in references) {
      reference.addEdit(change, newName);
    }
  }

  @override
  Future<RefactoringStatus> checkInitialConditions() {
    RefactoringStatus result = new RefactoringStatus();
    if (element.source.isInSystemLibrary) {
      String message = format(
          "The {0} '{1}' is defined in the SDK, so cannot be renamed.",
          getElementKindName(element),
          getElementQualifiedName(element));
      result.addFatalError(message);
    }
    if (isElementInPubCache(element)) {
      String message = format(
          "The {0} '{1}' is defined in a pub package, so cannot be renamed.",
          getElementKindName(element),
          getElementQualifiedName(element));
      result.addFatalError(message);
    }
    return new Future.value(result);
  }

  @override
  RefactoringStatus checkNewName() {
    RefactoringStatus result = new RefactoringStatus();
    if (newName == oldName) {
      result.addFatalError(
          "The new name must be different than the current name.");
    }
    return result;
  }

  @override
  Future<SourceChange> createChange() async {
    String changeName = "$refactoringName '$oldName' to '$newName'";
    change = new SourceChange(changeName);
    await fillChange();
    return change;
  }

  /**
   * Adds individual edits to [change].
   */
  Future fillChange();

  @override
  bool requiresPreview() {
    return false;
  }

  static String _getDisplayName(Element element) {
    if (element is ImportElement) {
      PrefixElement prefix = element.prefix;
      if (prefix != null) {
        return prefix.displayName;
      }
      return '';
    }
    return element.displayName;
  }
}
