// Copyright (c) 2020, 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/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/summary2/combinator.dart';
import 'package:analyzer/src/summary2/export.dart';

/// The scope defined by a class.
class ClassScope extends EnclosedScope {
  ClassScope(super.parent, ClassElement element) {
    element.accessors.forEach(_addPropertyAccessor);
    element.methods.forEach(_addGetter);
  }
}

/// The scope for the initializers in a constructor.
class ConstructorInitializerScope extends EnclosedScope {
  ConstructorInitializerScope(super.parent, ConstructorElement element) {
    element.parameters.forEach(_addGetter);
  }
}

/// A scope that is lexically enclosed in another scope.
class EnclosedScope implements Scope {
  final Scope _parent;
  final Map<String, Element> _getters = {};
  final Map<String, Element> _setters = {};

  EnclosedScope(Scope parent) : _parent = parent;

  Scope get parent => _parent;

  @override
  ScopeLookupResult lookup(String id) {
    var getter = _getters[id];
    var setter = _setters[id];
    if (getter != null || setter != null) {
      return ScopeLookupResultImpl(getter, setter);
    }

    return _parent.lookup(id);
  }

  void _addGetter(Element element) {
    var id = element.name;
    if (id != null) {
      _getters[id] ??= element;
    }
  }

  void _addPropertyAccessor(PropertyAccessorElement element) {
    if (element.isGetter) {
      _addGetter(element);
    } else {
      _addSetter(element);
    }
  }

  void _addSetter(Element element) {
    var name = element.name;
    if (name != null && name.endsWith('=')) {
      var id = name.substring(0, name.length - 1);
      _setters[id] ??= element;
    }
  }
}

/// The scope defined by an extension.
class ExtensionScope extends EnclosedScope {
  ExtensionScope(
    super.parent,
    ExtensionElement element,
  ) {
    element.accessors.forEach(_addPropertyAccessor);
    element.methods.forEach(_addGetter);
  }
}

class FormalParameterScope extends EnclosedScope {
  FormalParameterScope(
    super.parent,
    List<ParameterElement> elements,
  ) {
    for (var parameter in elements) {
      if (parameter is! FieldFormalParameterElement &&
          parameter is! SuperFormalParameterElement) {
        _addGetter(parameter);
      }
    }
  }
}

class ImportedElement {
  final Element element;

  /// This flag is set to `true` if [element] is available using import
  /// directives where every imported library re-exports the element, and
  /// every such `export` directive is marked as deprecated.
  final bool isFromDeprecatedExport;

  ImportedElement({
    required this.element,
    required this.isFromDeprecatedExport,
  });
}

class LibraryOrAugmentationScope extends EnclosedScope {
  final LibraryOrAugmentationElementImpl _container;
  final List<ExtensionElement> extensions = [];

  LibraryOrAugmentationScope(LibraryOrAugmentationElementImpl container)
      : _container = container,
        super(_LibraryOrAugmentationImportScope(container)) {
    extensions
        .addAll((_parent as _LibraryOrAugmentationImportScope).extensions);

    _container.prefixes.forEach(_addGetter);
    _container.library.units.forEach(_addUnitElements);

    // TODO(scheglov) I don't understand why it used to work, but broke now.
    // Now: when I'm adding `ImportElement2`.
    // We used to get it from `exportedReference`, but this is wrong.
    // These elements are declared in dart:core itself.
    if ('${_container.source.uri}' == 'dart:core') {
      _addGetter(DynamicElementImpl.instance);
      _addGetter(NeverElementImpl.instance);
    }
  }

  void _addExtension(ExtensionElement element) {
    _addGetter(element);
    if (!extensions.contains(element)) {
      extensions.add(element);
    }
  }

  void _addUnitElements(CompilationUnitElement compilationUnit) {
    compilationUnit.accessors.forEach(_addPropertyAccessor);
    compilationUnit.enums2.forEach(_addGetter);
    compilationUnit.extensions.forEach(_addExtension);
    compilationUnit.functions.forEach(_addGetter);
    compilationUnit.typeAliases.forEach(_addGetter);
    compilationUnit.mixins2.forEach(_addGetter);
    compilationUnit.classes.forEach(_addGetter);
  }
}

class LocalScope extends EnclosedScope {
  LocalScope(super.parent);

  void add(Element element) {
    _addGetter(element);
  }
}

class PrefixScope implements Scope {
  final LibraryOrAugmentationElementImpl _container;
  final Map<String, ImportedElement> _getters = {};
  final Map<String, ImportedElement> _setters = {};
  final Set<ExtensionElement> _extensions = {};
  LibraryElement? _deferredLibrary;

  PrefixScope(this._container, PrefixElement? prefix) {
    final elementFactory = _container.session.elementFactory;
    for (final import in _container.libraryImports) {
      final importedUri = import.uri;
      if (importedUri is DirectiveUriWithLibrary &&
          import.prefix?.element == prefix) {
        final importedLibrary = importedUri.library;
        if (importedLibrary is LibraryElementImpl) {
          final combinators = import.combinators.build();
          for (final exportedReference in importedLibrary.exportedReferences) {
            final reference = exportedReference.reference;
            if (combinators.allows(reference.name)) {
              final element = elementFactory.elementOfReference(reference)!;
              final importedElement = ImportedElement(
                element: element,
                isFromDeprecatedExport:
                    _isFromDeprecatedExport(importedLibrary, exportedReference),
              );
              _add(importedElement);
            }
          }
          if (import.prefix is DeferredImportElementPrefix) {
            _deferredLibrary ??= importedLibrary;
          }
        }
      }
    }
  }

  @override
  ScopeLookupResult lookup(String id) {
    var deferredLibrary = _deferredLibrary;
    if (deferredLibrary != null && id == FunctionElement.LOAD_LIBRARY_NAME) {
      return ScopeLookupResultImpl(deferredLibrary.loadLibraryFunction, null);
    }

    var getter = _getters[id];
    var setter = _setters[id];
    return PrefixScopeLookupResult(getter, setter);
  }

  void _add(ImportedElement imported) {
    final element = imported.element;
    if (element is PropertyAccessorElement && element.isSetter) {
      _addTo(map: _setters, incoming: imported);
    } else {
      _addTo(map: _getters, incoming: imported);
      if (element is ExtensionElement) {
        _extensions.add(element);
      }
    }
  }

  void _addTo({
    required Map<String, ImportedElement> map,
    required ImportedElement incoming,
  }) {
    final id = incoming.element.displayName;
    final existing = map[id];

    if (existing == null) {
      map[id] = incoming;
      return;
    }

    if (existing.element == incoming.element) {
      map[id] = ImportedElement(
        element: incoming.element,
        isFromDeprecatedExport:
            existing.isFromDeprecatedExport && incoming.isFromDeprecatedExport,
      );
      return;
    }

    map[id] = ImportedElement(
      element: _merge(existing.element, incoming.element),
      isFromDeprecatedExport: false,
    );
  }

  Element _merge(Element existing, Element other) {
    if (_isSdkElement(existing)) {
      if (!_isSdkElement(other)) {
        return other;
      }
    } else {
      if (_isSdkElement(other)) {
        return existing;
      }
    }

    var conflictingElements = <Element>{};
    _addElement(conflictingElements, existing);
    _addElement(conflictingElements, other);

    return MultiplyDefinedElementImpl(
      _container.context,
      _container.session,
      conflictingElements.first.name!,
      conflictingElements.toList(),
    );
  }

  static void _addElement(
    Set<Element> conflictingElements,
    Element element,
  ) {
    if (element is MultiplyDefinedElementImpl) {
      conflictingElements.addAll(element.conflictingElements);
    } else {
      conflictingElements.add(element);
    }
  }

  /// Return `true` if [exportedReference] comes only from deprecated exports.
  static bool _isFromDeprecatedExport(
    LibraryElementImpl importedLibrary,
    ExportedReference exportedReference,
  ) {
    if (exportedReference is ExportedReferenceExported) {
      for (final location in exportedReference.locations) {
        final export = location.exportOf(importedLibrary);
        if (!export.hasDeprecated) {
          return false;
        }
      }
      return true;
    }
    return false;
  }

  static bool _isSdkElement(Element element) {
    if (element is DynamicElementImpl || element is NeverElementImpl) {
      return true;
    }
    if (element is MultiplyDefinedElement) {
      return false;
    }
    return element.library!.isInSdk;
  }
}

class PrefixScopeLookupResult implements ScopeLookupResult {
  final ImportedElement? importedGetter;
  final ImportedElement? importedSetter;

  PrefixScopeLookupResult(
    this.importedGetter,
    this.importedSetter,
  );

  @override
  Element? get getter => importedGetter?.element;

  @override
  Element? get setter => importedSetter?.element;
}

class ScopeLookupResultImpl implements ScopeLookupResult {
  @override
  final Element? getter;

  @override
  final Element? setter;

  ScopeLookupResultImpl(this.getter, this.setter);
}

class TypeParameterScope extends EnclosedScope {
  TypeParameterScope(
    super.parent,
    List<TypeParameterElement> elements,
  ) {
    elements.forEach(_addGetter);
  }
}

class _LibraryOrAugmentationImportScope implements Scope {
  final LibraryOrAugmentationElementImpl _container;
  final PrefixScope _nullPrefixScope;
  List<ExtensionElement>? _extensions;

  _LibraryOrAugmentationImportScope(LibraryOrAugmentationElementImpl container)
      : _container = container,
        _nullPrefixScope = PrefixScope(container, null);

  List<ExtensionElement> get extensions {
    return _extensions ??= {
      ..._nullPrefixScope._extensions,
      for (var prefix in _container.prefixes)
        ...(prefix.scope as PrefixScope)._extensions,
    }.toList();
  }

  @override
  ScopeLookupResult lookup(String id) {
    return _nullPrefixScope.lookup(id);
  }
}
