// 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);
    }
  }
}
