// 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 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.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_core.dart';
import 'package:analyzer_plugin/utilities/range_factory.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 {
    var unit = libraryResult.unit;
    var path = libraryResult.path;
    if (unit == null || path == null) {
      // We should never reach this point because the libraryResult should be
      // valid.
      return SourceChange('');
    }
    var filteredImportedElements =
        _filterImportedElements(importedElementsList);
    var libraryElement = libraryResult.libraryElement;
    var uriConverter = libraryResult.session.uriConverter;
    var existingImports = <ImportDirective>[];
    for (var directive in unit.directives) {
      if (directive is ImportDirective) {
        existingImports.add(directive);
      }
    }

    var builder = ChangeBuilder(session: libraryResult.session);
    await builder.addDartFileEdit(path, (builder) {
      for (var importedElements in filteredImportedElements) {
        var 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.
          //
          var importedFile = resourceProvider.getFile(importedElements.path);
          var uri = uriConverter.pathToUri(importedFile.path);
          var importedSource = importedFile.createSource(uri);
          var importUri = _getLibrarySourceUri(libraryElement, importedSource);
          var description = _getInsertionDescription(importUri);
          builder.addInsertion(description.offset, (builder) {
            for (var 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 (var 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.
          //
          var updateMap = <ImportDirective, _ImportUpdate>{};
          for (var requiredName in importedElements.elements) {
            _computeUpdate(updateMap, matchingImports, requiredName);
          }
          //
          // Apply the edits.
          //
          for (var entry in updateMap.entries) {
            var directive = entry.key;
            var update = entry.value;
            var namesToUnhide = update.namesToUnhide;
            var namesToShow = update.namesToShow;
            namesToShow.sort();
            var combinators = directive.combinators;
            var combinatorCount = combinators.length;
            for (var combinatorIndex = 0;
                combinatorIndex < combinatorCount;
                combinatorIndex++) {
              var combinator = combinators[combinatorIndex];
              if (combinator is HideCombinator && namesToUnhide.isNotEmpty) {
                var hiddenNames = combinator.hiddenNames;
                var nameCount = hiddenNames.length;
                var first = -1;
                for (var 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 {
                      var precedingNode = directive.prefix ??
                          directive.deferredKeyword ??
                          directive.uri;
                      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, (builder) {
                  for (var 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 (var name in names) {
        if (name.name == requiredName) {
          return true;
        }
      }
      return false;
    }

    late ImportDirective preferredDirective;
    var bestEditCount = -1;
    var deleteHide = false;
    var addShow = false;

    for (var directive in matchingImports) {
      var combinators = directive.combinators;
      if (combinators.isEmpty) {
        return;
      }
      var hasHide = false;
      var needsShow = false;
      var editCount = 0;
      for (var 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;
      }
    }

    var update = updateMap.putIfAbsent(
        preferredDirective, () => _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) {
    var filteredList = <ImportedElements>[];
    for (var elements in originalList) {
      var originalElements = elements.elements;
      var filteredElements = originalElements.toList();
      for (var name in originalElements) {
        if (_hasElement(elements.prefix, name)) {
          filteredElements.remove(name);
        }
      }
      if (originalElements.length == filteredElements.length) {
        filteredList.add(elements);
      } else if (filteredElements.isNotEmpty) {
        filteredList.add(
            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) {
    var matchingImports = <ImportDirective>[];
    for (var 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) {
    var unit = libraryResult.unit;
    if (unit == null) {
      // We should never reach this point because the libraryResult should be
      // valid.
      return _InsertionDescription(0, after: 2);
    }
    LibraryDirective? libraryDirective;
    var importDirectives = <ImportDirective>[];
    var otherDirectives = <Directive>[];
    for (var 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 _InsertionDescription(0, after: 2);
        }
        return _InsertionDescription(otherDirectives[0].offset, after: 2);
      }
      return _InsertionDescription(libraryDirective.end, before: 2);
    }
    // TODO(brianwilkerson) Fix this to find the right location.
    // See DartFileEditBuilderImpl._addLibraryImports for inspiration.
    return _InsertionDescription(importDirectives.last.end, before: 1);
  }

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

  bool _hasElement(String prefix, String name) {
    var scope = libraryResult.libraryElement.scope;

    if (prefix.isNotEmpty) {
      var prefixElement = scope.lookup(prefix).getter;
      if (prefixElement is PrefixElement) {
        scope = prefixElement.scope;
      } else {
        return false;
      }
    }

    var lookupResult = scope.lookup(name);
    return lookupResult.getter != null || lookupResult.setter != null;
  }

  /// 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) {
    var importElement = import.element;
    if (importElement == null) {
      return false;
    }
    var library = 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})
      : newLinesBefore = before,
        newLinesAfter = after;
}
