// 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 test.services.completion.suggestion;

import 'dart:async';

import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart'
    show CompletionRequest, CompletionResult;
import 'package:analysis_server/src/services/completion/completion_core.dart';
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/index/index.dart';
import 'package:analysis_server/src/services/index/local_memory_index.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:unittest/unittest.dart';

import '../../abstract_single_unit.dart';
import '../../utils.dart';

main() {
  initializeTestEnvironment();
  defineReflectiveTests(DartCompletionManagerTest);
}

/**
 * Returns a [Future] that completes after pumping the event queue [times]
 * times. By default, this should pump the event queue enough times to allow
 * any code to run, as long as it's not waiting on some external event.
 */
Future pumpEventQueue([int times = 20]) {
  if (times == 0) return new Future.value();
  // We use a delayed future to allow microtask events to finish. The
  // Future.value or Future() constructors use scheduleMicrotask themselves and
  // would therefore not wait for microtask callbacks that are scheduled after
  // invoking this method.
  return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1));
}

@reflectiveTest
class DartCompletionManagerTest extends AbstractSingleUnitTest {
  Index index;
  SearchEngineImpl searchEngine;
  Source source;
  DartCompletionManager manager;
  MockCompletionContributor contributor1;
  MockCompletionContributor contributor2;
  CompletionSuggestion suggestion1;
  CompletionSuggestion suggestion2;
  bool _continuePerformingAnalysis = true;

  void resolveLibrary() {
    context.resolveCompilationUnit(
        source, context.computeLibraryElement(source));
  }

  @override
  void setUp() {
    super.setUp();
    index = createLocalMemoryIndex();
    searchEngine = new SearchEngineImpl(index);
    source = addSource('/does/not/exist.dart', '');
    manager =
        new DartCompletionManager.create(context, searchEngine, source, []);
    suggestion1 = new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
        DART_RELEVANCE_DEFAULT, "suggestion1", 1, 1, false, false);
    suggestion2 = new CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER,
        DART_RELEVANCE_DEFAULT, "suggestion2", 2, 2, false, false);
    new Future(_performAnalysis);
  }

  @override
  void tearDown() {
    _continuePerformingAnalysis = false;
  }

  test_compute_fastAndFull() {
    contributor1 = new MockCompletionContributor(suggestion1, null);
    contributor2 = new MockCompletionContributor(null, suggestion2);
    manager.contributors = [contributor1, contributor2];
    int count = 0;
    bool done = false;
    CompletionRequest completionRequest =
        new CompletionRequestImpl(context, provider, searchEngine, source, 0);
    manager.results(completionRequest).listen((CompletionResult r) {
      bool isLast = r is CompletionResultImpl ? r.isLast : true;
      switch (++count) {
        case 1:
          contributor1.assertCalls(context, source, 0, searchEngine);
          expect(contributor1.fastCount, equals(1));
          expect(contributor1.fullCount, equals(0));
          contributor2.assertCalls(context, source, 0, searchEngine);
          expect(contributor2.fastCount, equals(1));
          expect(contributor2.fullCount, equals(1));
          expect(isLast, isTrue);
          expect(r.suggestions, hasLength(2));
          expect(r.suggestions, contains(suggestion1));
          expect(r.suggestions, contains(suggestion2));
          resolveLibrary();
          break;
        default:
          fail('unexpected');
      }
    }, onDone: () {
      done = true;
      // There is only one notification
      expect(count, equals(1));
    });
    return pumpEventQueue(250).then((_) {
      expect(done, isTrue);
    });
  }

  test_compute_fastOnly() {
    contributor1 = new MockCompletionContributor(suggestion1, null);
    contributor2 = new MockCompletionContributor(suggestion2, null);
    manager.contributors = [contributor1, contributor2];
    int count = 0;
    bool done = false;
    CompletionRequest completionRequest =
        new CompletionRequestImpl(context, provider, searchEngine, source, 0);
    manager.results(completionRequest).listen((CompletionResult r) {
      bool isLast = r is CompletionResultImpl ? r.isLast : true;
      switch (++count) {
        case 1:
          contributor1.assertCalls(context, source, 0, searchEngine);
          expect(contributor1.fastCount, equals(1));
          expect(contributor1.fullCount, equals(0));
          contributor2.assertCalls(context, source, 0, searchEngine);
          expect(contributor2.fastCount, equals(1));
          expect(contributor2.fullCount, equals(0));
          expect(isLast, isTrue);
          expect(r.suggestions, hasLength(2));
          expect(r.suggestions, contains(suggestion1));
          expect(r.suggestions, contains(suggestion2));
          break;
        default:
          fail('unexpected');
      }
    }, onDone: () {
      done = true;
      expect(count, equals(1));
    });
    return pumpEventQueue().then((_) {
      expect(done, isTrue);
    });
  }

  void _performAnalysis() {
    if (!_continuePerformingAnalysis) {
      return;
    }
    context.performAnalysisTask();
    new Future(_performAnalysis);
  }
}

class MockCompletionContributor extends DartCompletionContributor {
  final CompletionSuggestion fastSuggestion;
  final CompletionSuggestion fullSuggestion;
  int fastCount = 0;
  int fullCount = 0;
  DartCompletionRequest request;

  MockCompletionContributor(this.fastSuggestion, this.fullSuggestion);

  assertCalls(AnalysisContext context, Source source, int offset,
      SearchEngine searchEngine) {
    expect(request.context, equals(context));
    expect(request.source, equals(source));
    expect(request.offset, equals(offset));
    expect(request.searchEngine, equals(searchEngine));
  }

  assertFull(int fullCount) {
    expect(this.fastCount, equals(1));
    expect(this.fullCount, equals(fullCount));
  }

  @override
  bool computeFast(DartCompletionRequest request) {
    this.request = request;
    fastCount++;
    if (fastSuggestion != null) {
      request.addSuggestion(fastSuggestion);
    }
    return fastSuggestion != null;
  }

  @override
  Future<bool> computeFull(DartCompletionRequest request) {
    this.request = request;
    fullCount++;
    if (fullSuggestion != null) {
      request.addSuggestion(fullSuggestion);
    }
    return new Future.value(fullSuggestion != null);
  }
}
