// 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/src/analysis_server.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analysis_server/src/provisional/completion/completion_core.dart'
    show CompletionRequest, CompletionResult;
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 '../../operation/operation_queue_test.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;
    AnalysisServer server = new AnalysisServerMock(searchEngine: searchEngine);
    CompletionRequest completionRequest =
        new CompletionRequestImpl(server, context, 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().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;
    AnalysisServer server = new AnalysisServerMock(searchEngine: searchEngine);
    CompletionRequest completionRequest =
        new CompletionRequestImpl(server, context, 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);
  }
}
