// Copyright (c) 2019, 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:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer_plugin/src/utilities/change_builder/dart/syntactic_scope.dart';
import 'package:meta/meta.dart';

ImportLibraryRequest importLibraryElementImpl({
  @required ResolvedLibraryResult targetResolvedLibrary,
  @required String targetPath,
  @required int targetOffset,
  @required LibraryElement requestedLibrary,
  @required Element requestedElement,
}) {
  var targetLibrary = targetResolvedLibrary.element;

  var requestedLibraryUri = requestedLibrary.source.uri;
  var requestedElementUri = requestedElement.librarySource.uri;
  var requestedName = requestedElement.displayName;

  // If the element is defined in this library, then no prefix needed.
  if (targetLibrary == requestedElement.library) {
    return ImportLibraryRequest(null, null);
  }

  var requestedElements = requestedLibrary.exportNamespace.definedNames;
  _removeEntriesForDynamicAndNever(requestedElements);

  // Find URIs of all libraries that import the requested name into the target.
  var unprefixedNameUriSet = Set<Uri>();
  for (var import in targetLibrary.imports) {
    var definedNames = import.namespace.definedNames;
    if (import.prefix == null) {
      var element = definedNames[requestedName];
      if (element != null) {
        unprefixedNameUriSet.add(element.librarySource.uri);
      }
    }
  }

  // Find names that will be shadowed by a new unprefixed import.
  var collector = NotSyntacticScopeReferencedNamesCollector(
    targetResolvedLibrary.element,
    requestedElements.keys.toSet(),
  );
  for (var resolvedUnit in targetResolvedLibrary.units) {
    resolvedUnit.unit.accept(collector);
  }

  // Find names that will shadow unprefixed references.
  var scopeNames = Set<String>();
  targetLibrary.accept(_TopLevelNamesCollector(scopeNames));
  for (var resolvedUnit in targetResolvedLibrary.units) {
    if (resolvedUnit.path == targetPath) {
      resolvedUnit.unit.accept(
        SyntacticScopeNamesCollector(scopeNames, targetOffset),
      );
    }
  }

  var canUseUnprefixedImport = true;

  // If a name is inherited, it will be shadowed by a new unprefixed import.
  if (collector.inheritedNames.isNotEmpty) {
    canUseUnprefixedImport = false;
  }

  // If a name is imported, and it is not the same as the one from the
  // requested library, then a new unprefixed import will cause ambiguity.
  for (var name in collector.importedNames.keys) {
    var importedUri = collector.importedNames[name];
    var requestedUri = requestedElements[name]?.librarySource?.uri;
    if (requestedUri != importedUri) {
      canUseUnprefixedImport = false;
      break;
    }
  }

  // If syntactic scope at the offset has the requested name, then the name
  // from an unprefixed import will be shadowed.
  if (scopeNames.contains(requestedName)) {
    canUseUnprefixedImport = false;
  }

  // If the requested name is ambiguous from existing unprefixed imports,
  // or is not the same element as the one from the requested library, then
  // we cannot use unprefixed import.
  if (unprefixedNameUriSet.isNotEmpty) {
    if (unprefixedNameUriSet.length > 1 ||
        unprefixedNameUriSet.first != requestedElementUri) {
      canUseUnprefixedImport = false;
    }
  }

  // Find import prefixes with which the name is ambiguous.
  var ambiguousWithImportPrefixes = Set<String>();
  for (var import in targetLibrary.imports) {
    var definedNames = import.namespace.definedNames;
    if (import.prefix != null) {
      var prefix = import.prefix.name;
      var prefixedName = '$prefix.$requestedName';
      var importedElement = definedNames[prefixedName];
      if (importedElement != null &&
          importedElement.librarySource.uri != requestedElementUri) {
        ambiguousWithImportPrefixes.add(prefix);
      }
    }
  }

  // Check for existing imports of the requested library.
  for (var import in targetLibrary.imports) {
    if (import.importedLibrary.source.uri == requestedLibraryUri) {
      var importedNames = import.namespace.definedNames;
      if (import.prefix == null) {
        if (canUseUnprefixedImport &&
            importedNames.containsKey(requestedName)) {
          return ImportLibraryRequest(null, null);
        }
      } else {
        var prefix = import.prefix.name;
        var prefixedName = '$prefix.$requestedName';
        if (importedNames.containsKey(prefixedName) &&
            !ambiguousWithImportPrefixes.contains(prefix)) {
          return ImportLibraryRequest(null, prefix);
        }
      }
    }
  }

  // If the name cannot be used without import prefix, generate one.
  String prefix;
  if (!canUseUnprefixedImport) {
    prefix = 'prefix';
    for (var index = 0;; index++) {
      prefix = 'prefix$index';
      if (!collector.referencedNames.contains(prefix)) {
        break;
      }
    }
  }

  return ImportLibraryRequest(requestedLibraryUri, prefix);
}

/// The types `dynamic` and `Never` are part of 'dart:core', but have no
/// library.
void _removeEntriesForDynamicAndNever(Map<String, Element> requestedElements) {
  requestedElements.removeWhere((_, element) {
    if (element.librarySource == null) {
      assert(
          element.displayName == 'dynamic' || element.displayName == 'Never');
      return true;
    }
    return false;
  });
}

/// Information about a library to import.
class ImportLibraryRequest {
  /// The URI of the library to import, or `null` if the requested library is
  /// already imported, with the [prefix], so no new import is required.
  final Uri uri;

  /// The prefix with which ths requested library is already imported,
  /// or should be imported, or `null` is no prefix is necessary.
  final String prefix;

  ImportLibraryRequest(this.uri, this.prefix);
}

/// Element visitor that collects names of top-level elements.
class _TopLevelNamesCollector extends GeneralizingElementVisitor<void> {
  final Set<String> names;

  _TopLevelNamesCollector(this.names);

  @override
  void visitElement(Element element) {
    if (element is LibraryElement || element is CompilationUnitElement) {
      super.visitElement(element);
    } else if (element is ImportElement) {
      var prefix = element.prefix?.displayName;
      if (prefix != null) {
        names.add(prefix);
      }
    } else if (element.enclosingElement is CompilationUnitElement) {
      names.add(element.displayName);
    }
  }
}
