// 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/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/completion/dart_completion_manager.dart';
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import '../../abstract_single_unit.dart';
import '../../reflective_tests.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:unittest/unittest.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.CLASS,
        CompletionRelevance.DEFAULT,
        "suggestion1",
        1,
        1,
        false,
        false);
    suggestion2 = new CompletionSuggestion(
        CompletionSuggestionKind.CLASS,
        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);
  }
}
