// 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/dart_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, DART_RELEVANCE_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, DART_RELEVANCE_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,
          DART_RELEVANCE_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, DART_RELEVANCE_LOW);
        }
      }
    });
  }

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

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

    CompletionSuggestion suggestion =
        createSuggestion(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, DART_RELEVANCE_DEFAULT);
  }

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

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

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

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

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