// 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/protocol.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:unittest/unittest.dart';

import '../../abstract_single_unit.dart';
import '../../reflective_tests.dart';

main() {
  groupSep = ' | ';
  runReflectiveTests(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));
}

@ReflectiveTestCase()
class DartCompletionManagerTest extends AbstractSingleUnitTest {
  Index index;
  SearchEngineImpl searchEngine;
  Source source;
  DartCompletionManager manager;
  MockCompletionComputer computer1;
  MockCompletionComputer computer2;
  CompletionSuggestion suggestion1;
  CompletionSuggestion suggestion2;

  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(context, searchEngine, source, 0);
    suggestion1 = new CompletionSuggestion(
        CompletionSuggestionKind.INVOCATION,
        CompletionRelevance.DEFAULT,
        "suggestion1",
        1,
        1,
        false,
        false);
    suggestion2 = new CompletionSuggestion(
        CompletionSuggestionKind.IDENTIFIER,
        CompletionRelevance.DEFAULT,
        "suggestion2",
        2,
        2,
        false,
        false);
  }

  test_compute_fastAndFull() {
    computer1 = new MockCompletionComputer(suggestion1, null);
    computer2 = new MockCompletionComputer(null, suggestion2);
    manager.computers = [computer1, computer2];
    int count = 0;
    bool done = false;
    manager.results().listen((CompletionResult r) {
      switch (++count) {
        case 1:
          computer1.assertCalls(context, source, 0, searchEngine);
          computer2.assertCalls(context, source, 0, searchEngine);
          expect(r.last, isFalse);
          expect(r.suggestions, hasLength(1));
          expect(r.suggestions, contains(suggestion1));
          resolveLibrary();
          break;
        case 2:
          computer1.assertFull(0);
          computer2.assertFull(1);
          expect(r.last, 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(2));
    });
    return pumpEventQueue().then((_) {
      expect(done, isTrue);
    });
  }

  test_compute_fastOnly() {
    computer1 = new MockCompletionComputer(suggestion1, null);
    computer2 = new MockCompletionComputer(suggestion2, null);
    manager.computers = [computer1, computer2];
    int count = 0;
    bool done = false;
    manager.results().listen((CompletionResult r) {
      switch (++count) {
        case 1:
          computer1.assertCalls(context, source, 0, searchEngine);
          computer2.assertCalls(context, source, 0, searchEngine);
          expect(r.last, 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);
    });
  }
}

class MockCompletionComputer extends DartCompletionComputer {
  final CompletionSuggestion fastSuggestion;
  final CompletionSuggestion fullSuggestion;
  int fastCount = 0;
  int fullCount = 0;
  DartCompletionRequest request;

  MockCompletionComputer(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));
    expect(this.fastCount, equals(1));
    expect(this.fullCount, equals(0));
  }

  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.suggestions.add(fastSuggestion);
    }
    return fastSuggestion != null;
  }

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