// Copyright (c) 2021, 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/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';

/// Cached data about the extensions defined in a single analysis context.
class ExtensionCache {
  /// A set containing the paths of the compilation units that have been cached.
  /// The set is used to prevent caching the same data multiple times.
  final Set<String> processedUnits = {};

  /// A map from the name of a non-static public extension member to the set of
  /// paths to libraries defining an extension member with that name.
  final Map<String, Set<UnitInLibrary>> membersByName = {};

  /// Initialize a newly created cache.
  ExtensionCache();

  /// Fill the cache with data from the [result].
  void cacheFromResult(ResolvedUnitResult result) {
    var element = result.unit?.declaredElement;
    if (element != null) {
      _cacheFromElement(element);
      for (var library in result.libraryElement.importedLibraries) {
        _cacheLibrary(library);
      }
    }
  }

  /// Fill the cache with data from the [compilationUnit].
  void _cacheFromElement(CompilationUnitElement compilationUnit) {
    // Record that we've cached data for the compilation unit.
    var unitPath = _keyForUnit(compilationUnit);
    processedUnits.add(unitPath);

    // Flush any data that was previously cached for the compilation unit.
    for (var set in membersByName.values) {
      set.removeWhere((element) => element.unitPath == unitPath);
    }

    // Cache the data for the compilation unit.
    var libraryPath = compilationUnit.librarySource.fullName;
    for (var extension in compilationUnit.extensions) {
      var extensionName = extension.name;
      if (extensionName != null && !Identifier.isPrivateName(extensionName)) {
        for (var member in extension.accessors) {
          if (!member.isSynthetic) {
            _recordMember(unitPath, libraryPath, member.displayName);
          }
        }
        for (var member in extension.fields) {
          if (!member.isSynthetic) {
            _recordMember(unitPath, libraryPath, member.name);
          }
        }
        for (var member in extension.methods) {
          _recordMember(unitPath, libraryPath, member.name);
        }
      }
    }
  }

  /// Cache the data for the given [library] and every library exported from it
  /// if it hasn't already been cached.
  void _cacheLibrary(LibraryElement library) {
    if (_hasDataFor(library.definingCompilationUnit)) {
      return;
    }
    for (var unit in library.units) {
      _cacheFromElement(unit);
    }
    for (var exported in library.exportedLibraries) {
      _cacheLibrary(exported);
    }
  }

  /// Return `true` if the cache contains data for the [compilationUnit].
  bool _hasDataFor(CompilationUnitElement compilationUnit) {
    return processedUnits.contains(_keyForUnit(compilationUnit));
  }

  /// Return the key used in the [extensionCache] for the [compilationUnit].
  String _keyForUnit(CompilationUnitElement compilationUnit) =>
      compilationUnit.source.fullName;

  /// Record that an extension member with the given [name] is defined in the
  /// compilation unit with the [unitPath] in the library with the
  /// [libraryPath].
  void _recordMember(String unitPath, String libraryPath, String name) {
    membersByName
        .putIfAbsent(name, () => {})
        .add(UnitInLibrary(unitPath, libraryPath));
  }
}

/// A representation of a compilation unit in a library.
class UnitInLibrary {
  final String unitPath;
  final String libraryPath;

  UnitInLibrary(this.unitPath, this.libraryPath);
}
