// Copyright (c) 2014, 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.

library services.completion.dart.cache;

import 'dart:async';
import 'dart:collection';

import 'package:analysis_server/src/protocol_server.dart' hide Element,
    ElementKind;
import 'package:analysis_server/src/services/completion/completion_manager.dart';
import 'package:analysis_server/src/services/completion/suggestion_builder.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';

/**
 * The `DartCompletionCache` contains cached information from a prior code
 * completion operation.
 */
class DartCompletionCache extends CompletionCache {

  /**
   * A hash of the import directives
   * or `null` if nothing has been cached.
   */
  String _importKey;

  /**
   * Library prefix suggestions based upon imports,
   * or `null` if nothing has been cached.
   */
  List<CompletionSuggestion> libraryPrefixSuggestions;

  /**
   * Type suggestions based upon imports,
   * or `null` if nothing has been cached.
   */
  List<CompletionSuggestion> importedTypeSuggestions;

  /**
   * Suggestions for methods and functions that have void return type,
   * or `null` if nothing has been cached.
   */
  List<CompletionSuggestion> importedVoidReturnSuggestions;

  /**
   * Other suggestions based upon imports,
   * or `null` if nothing has been cached.
   */
  List<CompletionSuggestion> otherImportedSuggestions;

  /**
   * A collection of all imported completions
   * or `null` if nothing has been cached.
   */
  HashSet<String> _importedCompletions;

  /**
   * A map of simple identifier to imported class element
   * or `null` if nothing has been cached.
   */
  Map<String, ClassElement> importedClassMap;

  /**
   * The [ClassElement] for Object.
   */
  ClassElement _objectClassElement;

  DartCompletionCache(AnalysisContext context, Source source)
      : super(context, source);

  /**
   * Return a hash of the import directives for the cached import info
   * or `null` if nothing has been cached.
   */
  String get importKey => _importKey;

  /**
   * Return the [ClassElement] for Object.
   */
  ClassElement get objectClassElement {
    if (_objectClassElement == null) {
      Source coreUri = context.sourceFactory.forUri('dart:core');
      LibraryElement coreLib = context.getLibraryElement(coreUri);
      _objectClassElement = coreLib.getType('Object');
    }
    return _objectClassElement;
  }

  /**
   * Given a resolved compilation unit, compute suggestions based upon the
   * imports and other dart files (e.g. "part" files) in the library containing
   * the given compilation unit. The returned future completes when the cache
   * is populated.
   *
   * If [shouldWaitForLowPrioritySuggestions] is `true` then the returned
   * future will complete when the cache is fully populated. If `false`,
   * the returned future will complete sooner, but the cache will not include
   * the lower priority suggestions added as a result of a global search.
   * In this case, those lower priority suggestions will be added later
   * when the index has been updated and the global search completes.
   */
  Future<bool> computeImportInfo(CompilationUnit unit,
      SearchEngine searchEngine, bool shouldWaitForLowPrioritySuggestions) {
    importedTypeSuggestions = <CompletionSuggestion>[];
    libraryPrefixSuggestions = <CompletionSuggestion>[];
    otherImportedSuggestions = <CompletionSuggestion>[];
    importedVoidReturnSuggestions = <CompletionSuggestion>[];
    importedClassMap = new Map<String, ClassElement>();
    _importedCompletions = new HashSet<String>();

    // Assert that the compilation unit is resolved
    // and represents the expected source
    assert(unit.element.source == source);

    // Exclude elements from local library
    // because they are provided by LocalComputer
    Set<LibraryElement> excludedLibs = new Set<LibraryElement>();
    excludedLibs.add(unit.element.enclosingElement);

    // Determine the compilation unit defining the library containing
    // this compilation unit
    List<Source> libraries = context.getLibrariesContaining(source);
    assert(libraries != null);
    Source libSource = libraries.length > 0 ? libraries[0] : null;
    Future<CompilationUnit> futureLibUnit = _computeLibUnit(libSource, unit);

    // Include implicitly imported dart:core elements
    _addDartCoreSuggestions();

    // Include explicitly imported and part elements
    Future futureImportsCached = futureLibUnit.then((CompilationUnit libUnit) {
      _addImportedElemSuggestions(libSource, libUnit, excludedLibs);
      // Don't wait for search of lower relevance results to complete.
      // Set key indicating results are ready, and lower relevance results
      // will be added to the cache when the search completes.
      _importKey = _computeImportKey(unit);
      return true;
    });

    // Add non-imported elements as low relevance
    // after the imported element suggestions have been added
    Future<bool> futureAllCached = futureImportsCached.then((_) {
      return searchEngine.searchTopLevelDeclarations(
          '').then((List<SearchMatch> matches) {
        _addNonImportedElementSuggestions(matches, excludedLibs);
        return true;
      });
    });

    return shouldWaitForLowPrioritySuggestions ?
        futureAllCached :
        futureImportsCached;
  }

  /**
   * Return `true` if the import information is cached for the given
   * compilation unit.
   */
  bool isImportInfoCached(CompilationUnit unit) =>
      _importKey != null && _importKey == _computeImportKey(unit);

  /**
   * Add suggestions for implicitly imported elements in dart:core.
   */
  void _addDartCoreSuggestions() {
    Source coreUri = context.sourceFactory.forUri('dart:core');
    LibraryElement coreLib = context.getLibraryElement(coreUri);
    Namespace coreNamespace =
        new NamespaceBuilder().createPublicNamespaceForLibrary(coreLib);
    coreNamespace.definedNames.forEach((String name, Element elem) {
      if (elem is ClassElement) {
        importedClassMap[name] = elem;
      }
      _addSuggestion(elem, CompletionRelevance.DEFAULT);
    });
  }

  /**
   * Add suggestions for explicitly imported and part elements in the given
   * library. Add libraries that should not have their elements suggested
   * even as low priority to [excludedLibs].
   */
  void _addImportedElemSuggestions(Source libSource, CompilationUnit libUnit,
      Set<LibraryElement> excludedLibs) {
    if (libUnit != null) {
      libUnit.directives.forEach((Directive directive) {
        if (directive is ImportDirective) {
          ImportElement importElem = directive.element;
          if (importElem != null && importElem.importedLibrary != null) {
            if (directive.prefix == null) {
              Namespace importNamespace =
                  new NamespaceBuilder().createImportNamespaceForDirective(importElem);
              // Include top level elements
              importNamespace.definedNames.forEach((String name, Element elem) {
                if (elem is ClassElement) {
                  importedClassMap[name] = elem;
                }
                _addSuggestion(elem, CompletionRelevance.DEFAULT);
              });
            } else {
              // Exclude elements from prefixed imports
              // because they are provided by InvocationComputer
              _addLibraryPrefixSuggestion(importElem);
              excludedLibs.add(importElem.importedLibrary);
            }
          }
        } else if (directive is PartDirective) {
          CompilationUnitElement partElem = directive.element;
          if (partElem != null && partElem.source != source) {
            partElem.accept(new _NonLocalElementCacheVisitor(this));
          }
        }
      });
      if (libSource != source) {
        libUnit.element.accept(new _NonLocalElementCacheVisitor(this));
      }
    }
  }

  void _addLibraryPrefixSuggestion(ImportElement importElem) {
    CompletionSuggestion suggestion = null;
    String completion = importElem.prefix.displayName;
    if (completion != null && completion.length > 0) {
      suggestion = new CompletionSuggestion(
          CompletionSuggestionKind.INVOCATION,
          CompletionRelevance.DEFAULT,
          completion,
          completion.length,
          0,
          importElem.isDeprecated,
          false);
      LibraryElement lib = importElem.importedLibrary;
      if (lib != null) {
        suggestion.element = newElement_fromEngine(lib);
      }
      libraryPrefixSuggestions.add(suggestion);
      _importedCompletions.add(suggestion.completion);
    }
  }

  /**
   * Add suggestions for all top level elements in the context
   * excluding those elemnents for which suggestions have already been added.
   */
  void _addNonImportedElementSuggestions(List<SearchMatch> matches,
      Set<LibraryElement> excludedLibs) {
    matches.forEach((SearchMatch match) {
      if (match.kind == MatchKind.DECLARATION) {
        Element element = match.element;
        if (element.context == context &&
            element.isPublic &&
            !excludedLibs.contains(element.library) &&
            !_importedCompletions.contains(element.displayName)) {
          _addSuggestion(element, CompletionRelevance.LOW);
        }
      }
    });
  }

  /**
   * Add a suggestion for the given element.
   */
  void _addSuggestion(Element element, CompletionRelevance relevance) {

    if (element is ExecutableElement) {
      if (element.isOperator) {
        return;
      }
    }

    CompletionSuggestion suggestion =
        createElementSuggestion(element, relevance: relevance);

    if (element is ExecutableElement) {
      DartType returnType = element.returnType;
      if (returnType != null && returnType.isVoid) {
        importedVoidReturnSuggestions.add(suggestion);
      } else {
        otherImportedSuggestions.add(suggestion);
      }
    } else if (element is ClassElement) {
      importedTypeSuggestions.add(suggestion);
    } else {
      otherImportedSuggestions.add(suggestion);
    }
    _importedCompletions.add(suggestion.completion);
  }

  /**
   * Compute the hash of the imports for the given compilation unit.
   */
  String _computeImportKey(CompilationUnit unit) {
    StringBuffer sb = new StringBuffer();
    unit.directives.forEach((Directive directive) {
      sb.write(directive.toSource());
    });
    return sb.toString();
  }

  /**
   * Compute the library unit for the given library source,
   * where the [unit] is the resolved compilation unit associated with [source].
   */
  Future<CompilationUnit> _computeLibUnit(Source libSource,
      CompilationUnit unit) {
    // If the sources are the same then we already have the library unit
    if (libSource == source) {
      return new Future.value(unit);
    }
    // If [source] is a part, then compute the library unit
    if (libSource != null) {
      return context.computeResolvedCompilationUnitAsync(libSource, libSource);
    }
    return new Future.value(null);
  }
}

/**
 * A visitor for building suggestions based upon the elements defined by
 * a source file contained in the same library but not the same as
 * the source in which the completions are being requested.
 */
class _NonLocalElementCacheVisitor extends GeneralizingElementVisitor {
  final DartCompletionCache cache;

  _NonLocalElementCacheVisitor(this.cache);

  @override
  void visitClassElement(ClassElement element) {
    cache._addSuggestion(element, CompletionRelevance.DEFAULT);
  }

  @override
  void visitCompilationUnitElement(CompilationUnitElement element) {
    element.visitChildren(this);
  }

  @override
  void visitElement(Element element) {
    // ignored
  }

  @override
  void visitFunctionElement(FunctionElement element) {
    cache._addSuggestion(element, CompletionRelevance.DEFAULT);
  }

  @override
  void visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
    cache._addSuggestion(element, CompletionRelevance.DEFAULT);
  }

  @override
  void visitTopLevelVariableElement(TopLevelVariableElement element) {
    cache._addSuggestion(element, CompletionRelevance.DEFAULT);
  }
}
