// 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:analysis_server/src/computer/computer_hover.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';

/// Cached data about the documentation associated with the elements declared in
/// a single analysis context.
class DocumentationCache {
  /// A shared instance for elements that have no documentation.
  static final DocumentationWithSummary _emptyDocs =
      DocumentationWithSummary(full: '', summary: '');

  /// The object used to compute the documentation associated with a single
  /// element.
  final DartdocDirectiveInfo dartdocDirectiveInfo;

  /// The documentation associated with the elements that have been cached. The
  /// cache is keyed by the path of the file containing the declaration of the
  /// element and the qualified name of the element.
  final Map<String, Map<String, DocumentationWithSummary>> documentationCache =
      {};

  /// Initialize a newly created cache.
  DocumentationCache(this.dartdocDirectiveInfo);

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

  /// Return the data cached for the given [element], or `null` if there is no
  /// cached data.
  DocumentationWithSummary? dataFor(Element element) {
    var parent = element.enclosingElement;
    if (parent == null) {
      return null;
    }
    var key = element.name;
    if (key == null) {
      return null;
    }
    if (parent is! CompilationUnitElement) {
      var parentName = parent.name;
      if (parentName == null) {
        return null;
      }
      key = '$parentName.$key';
      parent = parent.enclosingElement;
    }
    if (parent is CompilationUnitElement) {
      var elementMap = documentationCache[_keyForUnit(parent)];
      return elementMap?[key];
    }
    return null;
  }

  /// Fill the cache with data from the [compilationUnit].
  void _cacheFromElement(CompilationUnitElement compilationUnit) {
    var elementMap =
        documentationCache.putIfAbsent(_keyForUnit(compilationUnit), () => {});
    for (var element in compilationUnit.accessors) {
      if (!element.isSynthetic) {
        elementMap.cacheTopLevelElement(dartdocDirectiveInfo, element);
      }
    }
    for (var element in compilationUnit.enums) {
      var parentKey =
          elementMap.cacheTopLevelElement(dartdocDirectiveInfo, element);
      if (parentKey != null) {
        for (var member in element.fields) {
          elementMap.cacheMember(dartdocDirectiveInfo, parentKey, member);
        }
      }
    }
    for (var element in compilationUnit.extensions) {
      var parentKey =
          elementMap.cacheTopLevelElement(dartdocDirectiveInfo, element);
      if (parentKey != null) {
        for (var member in element.accessors) {
          if (!member.isSynthetic) {
            elementMap.cacheMember(dartdocDirectiveInfo, parentKey, member);
          }
        }
        for (var member in element.fields) {
          if (!member.isSynthetic) {
            elementMap.cacheMember(dartdocDirectiveInfo, parentKey, member);
          }
        }
        for (var member in element.methods) {
          elementMap.cacheMember(dartdocDirectiveInfo, parentKey, member);
        }
      }
    }
    for (var element in compilationUnit.functions) {
      elementMap.cacheTopLevelElement(dartdocDirectiveInfo, element);
    }
    for (var element in [
      ...compilationUnit.mixins,
      ...compilationUnit.classes
    ]) {
      var parentKey =
          elementMap.cacheTopLevelElement(dartdocDirectiveInfo, element);
      if (parentKey != null) {
        for (var member in element.accessors) {
          if (!element.isSynthetic) {
            elementMap.cacheMember(dartdocDirectiveInfo, parentKey, member);
          }
        }
        for (var member in element.fields) {
          if (!element.isSynthetic) {
            elementMap.cacheMember(dartdocDirectiveInfo, parentKey, member);
          }
        }
        for (var member in element.methods) {
          elementMap.cacheMember(dartdocDirectiveInfo, parentKey, member);
        }
      }
    }
    for (var element in compilationUnit.topLevelVariables) {
      if (!element.isSynthetic) {
        elementMap.cacheTopLevelElement(dartdocDirectiveInfo, element);
      }
    }
    for (var element in compilationUnit.typeAliases) {
      elementMap.cacheTopLevelElement(dartdocDirectiveInfo, element);
    }
  }

  /// 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 documentationCache.containsKey(_keyForUnit(compilationUnit));
  }

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

extension on Map<String, DocumentationWithSummary> {
  /// Cache the data associated with the top-level [element], and return the
  /// [key] used for the element. This does not cache any data associated with
  /// any other elements, including children of the [element].
  String? cacheTopLevelElement(
      DartdocDirectiveInfo dartdocDirectiveInfo, Element element) {
    var key = element.name;
    if (key == null) {
      return null;
    }
    cacheElement(dartdocDirectiveInfo, key, element);
    return key;
  }

  /// Cache the data associated with the [member] element given that the key
  /// associated with the member's parent is [parentKey].
  void cacheMember(DartdocDirectiveInfo dartdocDirectiveInfo, String parentKey,
      Element member) {
    var name = member.name;
    if (name == null) {
      return null;
    }
    cacheElement(dartdocDirectiveInfo, '$parentKey.$name', member);
  }

  /// Cache the data associated with the [element], using the given [key].
  DocumentationWithSummary? cacheElement(
      DartdocDirectiveInfo dartdocDirectiveInfo, String key, Element element) {
    var documentation = DartUnitHoverComputer.computeDocumentation(
        dartdocDirectiveInfo, element,
        includeSummary: true);
    if (documentation is DocumentationWithSummary) {
      return this[key] = documentation;
    }
    return this[key] = DocumentationCache._emptyDocs;
  }
}
