// Copyright (c) 2017, 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 'dart:async';

import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/uri_converter.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
import 'package:front_end/src/base/syntactic_entity.dart';
import 'package:path/src/context.dart';

/**
 * An object used to compute a set of edits to add imports to a given library in
 * order to make a given set of elements visible.
 *
 * This is used to implement the `edit.importElements` request.
 */
class ImportElementsComputer {
  /**
   * The resource provider used to access the file system.
   */
  final ResourceProvider resourceProvider;

  /**
   * The resolution result associated with the defining compilation unit of the
   * library to which imports might be added.
   */
  final ResolvedUnitResult libraryResult;

  /**
   * Initialize a newly created builder.
   */
  ImportElementsComputer(this.resourceProvider, this.libraryResult);

  /**
   * Create the edits that will cause the list of [importedElements] to be
   * imported into the library at the given [path].
   */
  Future<SourceChange> createEdits(
      List<ImportedElements> importedElementsList) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    List<ImportedElements> filteredImportedElements =
        _filterImportedElements(importedElementsList);
    LibraryElement libraryElement = libraryResult.libraryElement;
    UriConverter uriConverter = libraryResult.session.uriConverter;
    List<ImportDirective> existingImports = <ImportDirective>[];
    for (var directive in libraryResult.unit.directives) {
      if (directive is ImportDirective) {
        existingImports.add(directive);
      }
    }

    DartChangeBuilder builder = new DartChangeBuilder(libraryResult.session);
    await builder.addFileEdit(libraryResult.path,
        (DartFileEditBuilder builder) {
      for (ImportedElements importedElements in filteredImportedElements) {
        List<ImportDirective> matchingImports =
            _findMatchingImports(existingImports, importedElements);
        if (matchingImports.isEmpty) {
          //
          // The required library is not being imported with a matching prefix,
          // so we need to add an import.
          //
          File importedFile = resourceProvider.getFile(importedElements.path);
          Uri uri = uriConverter.pathToUri(importedFile.path);
          Source importedSource = importedFile.createSource(uri);
          String importUri =
              _getLibrarySourceUri(libraryElement, importedSource);
          _InsertionDescription description =
              _getInsertionDescription(importUri);
          builder.addInsertion(description.offset, (DartEditBuilder builder) {
            for (int i = 0; i < description.newLinesBefore; i++) {
              builder.writeln();
            }
            builder.write("import '");
            builder.write(importUri);
            builder.write("'");
            if (importedElements.prefix.isNotEmpty) {
              builder.write(' as ');
              builder.write(importedElements.prefix);
            }
            builder.write(';');
            for (int i = 0; i < description.newLinesAfter; i++) {
              builder.writeln();
            }
          });
        } else {
          //
          // There are some imports of the library with a matching prefix. We
          // need to determine whether the names are already visible or whether
          // we need to make edits to make them visible.
          //
          // Compute the edits that need to be made.
          //
          Map<ImportDirective, _ImportUpdate> updateMap =
              <ImportDirective, _ImportUpdate>{};
          for (String requiredName in importedElements.elements) {
            _computeUpdate(updateMap, matchingImports, requiredName);
          }
          //
          // Apply the edits.
          //
          for (ImportDirective directive in updateMap.keys) {
            _ImportUpdate update = updateMap[directive];
            List<String> namesToUnhide = update.namesToUnhide;
            List<String> namesToShow = update.namesToShow;
            namesToShow.sort();
            NodeList<Combinator> combinators = directive.combinators;
            int combinatorCount = combinators.length;
            for (int combinatorIndex = 0;
                combinatorIndex < combinatorCount;
                combinatorIndex++) {
              Combinator combinator = combinators[combinatorIndex];
              if (combinator is HideCombinator && namesToUnhide.isNotEmpty) {
                NodeList<SimpleIdentifier> hiddenNames = combinator.hiddenNames;
                int nameCount = hiddenNames.length;
                int first = -1;
                for (int nameIndex = 0; nameIndex < nameCount; nameIndex++) {
                  if (namesToUnhide.contains(hiddenNames[nameIndex].name)) {
                    if (first < 0) {
                      first = nameIndex;
                    }
                  } else {
                    if (first >= 0) {
                      // Remove a range of names.
                      builder.addDeletion(range.startStart(
                          hiddenNames[first], hiddenNames[nameIndex]));
                      first = -1;
                    }
                  }
                }
                if (first == 0) {
                  // Remove the whole combinator.
                  if (combinatorIndex == 0) {
                    if (combinatorCount > 1) {
                      builder.addDeletion(range.startStart(
                          combinator, combinators[combinatorIndex + 1]));
                    } else {
                      SyntacticEntity precedingNode = directive.prefix ??
                          directive.deferredKeyword ??
                          directive.uri;
                      if (precedingNode == null) {
                        builder.addDeletion(range.node(combinator));
                      } else {
                        builder.addDeletion(
                            range.endEnd(precedingNode, combinator));
                      }
                    }
                  } else {
                    builder.addDeletion(range.endEnd(
                        combinators[combinatorIndex - 1], combinator));
                  }
                } else if (first > 0) {
                  // Remove a range of names that includes the last name.
                  builder.addDeletion(range.endEnd(
                      hiddenNames[first - 1], hiddenNames[nameCount - 1]));
                }
              } else if (combinator is ShowCombinator &&
                  namesToShow.isNotEmpty) {
                // TODO(brianwilkerson) Add the names in alphabetic order.
                builder.addInsertion(combinator.shownNames.last.end,
                    (DartEditBuilder builder) {
                  for (String nameToShow in namesToShow) {
                    builder.write(', ');
                    builder.write(nameToShow);
                  }
                });
              }
            }
          }
        }
      }
    });
    return builder.sourceChange;
  }

  /**
   * Choose the import for which the least amount of work is required,
   * preferring to do no work in there is an import that already makes the name
   * visible, and preferring to remove hide combinators rather than add show
   * combinators.
   *
   * The name is visible without needing any changes if:
   * - there is an import with no combinators,
   * - there is an import with only hide combinators and none of them hide the
   *   name,
   * - there is an import that shows the name and doesn't subsequently hide the
   *   name.
   */
  void _computeUpdate(Map<ImportDirective, _ImportUpdate> updateMap,
      List<ImportDirective> matchingImports, String requiredName) {
    /**
     * Return `true` if the [requiredName] is in the given list of [names].
     */
    bool nameIn(NodeList<SimpleIdentifier> names) {
      for (SimpleIdentifier name in names) {
        if (name.name == requiredName) {
          return true;
        }
      }
      return false;
    }

    ImportDirective preferredDirective = null;
    int bestEditCount = -1;
    bool deleteHide = false;
    bool addShow = false;

    for (ImportDirective directive in matchingImports) {
      NodeList<Combinator> combinators = directive.combinators;
      if (combinators.isEmpty) {
        return;
      }
      bool hasHide = false;
      bool needsShow = false;
      int editCount = 0;
      for (Combinator combinator in combinators) {
        if (combinator is HideCombinator) {
          if (nameIn(combinator.hiddenNames)) {
            hasHide = true;
            editCount++;
          }
        } else if (combinator is ShowCombinator) {
          if (needsShow || !nameIn(combinator.shownNames)) {
            needsShow = true;
            editCount++;
          }
        }
      }
      if (editCount == 0) {
        return;
      } else if (bestEditCount < 0 || editCount < bestEditCount) {
        preferredDirective = directive;
        bestEditCount = editCount;
        deleteHide = hasHide;
        addShow = needsShow;
      }
    }

    _ImportUpdate update = updateMap.putIfAbsent(
        preferredDirective, () => new _ImportUpdate(preferredDirective));
    if (deleteHide) {
      update.unhide(requiredName);
    }
    if (addShow) {
      update.show(requiredName);
    }
  }

  /**
   * Filter the given list of imported elements ([originalList]) so that only
   * the names that are not already defined still remain. Names that are already
   * defined are removed even if they might not resolve to the same name as in
   * the original source.
   */
  List<ImportedElements> _filterImportedElements(
      List<ImportedElements> originalList) {
    LibraryElement libraryElement = libraryResult.libraryElement;
    LibraryScope libraryScope = new LibraryScope(libraryElement);
    AstFactory factory = new AstFactoryImpl();
    List<ImportedElements> filteredList = <ImportedElements>[];
    for (ImportedElements elements in originalList) {
      List<String> originalElements = elements.elements;
      List<String> filteredElements = originalElements.toList();
      for (String name in originalElements) {
        Identifier identifier = factory
            .simpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1));
        if (elements.prefix.isNotEmpty) {
          SimpleIdentifier prefix = factory.simpleIdentifier(
              new StringToken(TokenType.IDENTIFIER, elements.prefix, -1));
          Token period = new SimpleToken(TokenType.PERIOD, -1);
          identifier = factory.prefixedIdentifier(prefix, period, identifier);
        }
        Element element = libraryScope.lookup(identifier, libraryElement);
        if (element != null) {
          filteredElements.remove(name);
        }
      }
      if (originalElements.length == filteredElements.length) {
        filteredList.add(elements);
      } else if (filteredElements.isNotEmpty) {
        filteredList.add(new ImportedElements(
            elements.path, elements.prefix, filteredElements));
      }
    }
    return filteredList;
  }

  /**
   * Return all of the import elements in the list of [existingImports] that
   * match the given specification of [importedElements], or an empty list if
   * there are no such imports.
   */
  List<ImportDirective> _findMatchingImports(
      List<ImportDirective> existingImports,
      ImportedElements importedElements) {
    List<ImportDirective> matchingImports = <ImportDirective>[];
    for (ImportDirective existingImport in existingImports) {
      if (_matches(existingImport, importedElements)) {
        matchingImports.add(existingImport);
      }
    }
    return matchingImports;
  }

  /**
   * Return the offset at which an import of the given [importUri] should be
   * inserted.
   *
   * Partially copied from DartFileEditBuilderImpl.
   */
  _InsertionDescription _getInsertionDescription(String importUri) {
    CompilationUnit unit = libraryResult.unit;
    LibraryDirective libraryDirective;
    List<ImportDirective> importDirectives = <ImportDirective>[];
    List<Directive> otherDirectives = <Directive>[];
    for (Directive directive in unit.directives) {
      if (directive is LibraryDirective) {
        libraryDirective = directive;
      } else if (directive is ImportDirective) {
        importDirectives.add(directive);
      } else {
        otherDirectives.add(directive);
      }
    }
    if (importDirectives.isEmpty) {
      if (libraryDirective == null) {
        if (otherDirectives.isEmpty) {
          // TODO(brianwilkerson) Insert after any non-doc comments.
          return new _InsertionDescription(0, after: 2);
        }
        return new _InsertionDescription(otherDirectives[0].offset, after: 2);
      }
      return new _InsertionDescription(libraryDirective.end, before: 2);
    }
    // TODO(brianwilkerson) Fix this to find the right location.
    // See DartFileEditBuilderImpl._addLibraryImports for inspiration.
    return new _InsertionDescription(importDirectives.last.end, before: 1);
  }

  /**
   * Computes the best URI to import [what] into [from].
   *
   * Copied from DartFileEditBuilderImpl.
   */
  String _getLibrarySourceUri(LibraryElement from, Source what) {
    String whatPath = what.fullName;
    // check if an absolute URI (such as 'dart:' or 'package:')
    Uri whatUri = what.uri;
    String whatUriScheme = whatUri.scheme;
    if (whatUriScheme != '' && whatUriScheme != 'file') {
      return whatUri.toString();
    }
    // compute a relative URI
    Context context = resourceProvider.pathContext;
    String fromFolder = context.dirname(from.source.fullName);
    String relativeFile = context.relative(whatPath, from: fromFolder);
    return context.split(relativeFile).join('/');
  }

  /**
   * Return `true` if the given [import] matches the given specification of
   * [importedElements]. They will match if they import the same library using
   * the same prefix.
   */
  bool _matches(ImportDirective import, ImportedElements importedElements) {
    LibraryElement library = (import.element as ImportElement).importedLibrary;
    return library != null &&
        library.source.fullName == importedElements.path &&
        (import.prefix?.name ?? '') == importedElements.prefix;
  }
}

/**
 * Information about how a given import directive needs to be updated in order
 * to make the required names visible.
 */
class _ImportUpdate {
  /**
   * The import directive to be updated.
   */
  final ImportDirective import;

  /**
   * The list of names that are currently hidden that need to not be hidden.
   */
  final List<String> namesToUnhide = <String>[];

  /**
   * The list of names that need to be added to show clauses.
   */
  final List<String> namesToShow = <String>[];

  /**
   * Initialize a newly created information holder to hold information about
   * updates to the given [import].
   */
  _ImportUpdate(this.import);

  /**
   * Record that the given [name] needs to be added to show combinators.
   */
  void show(String name) {
    namesToShow.add(name);
  }

  /**
   * Record that the given [name] needs to be removed from hide combinators.
   */
  void unhide(String name) {
    namesToUnhide.add(name);
  }
}

class _InsertionDescription {
  final int newLinesBefore;
  final int offset;
  final int newLinesAfter;

  _InsertionDescription(this.offset, {int before: 0, int after: 0})
      : this.newLinesBefore = before,
        this.newLinesAfter = after;
}
