// Copyright (c) 2017, 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.

import 'dart:async';

import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer_plugin/plugin/occurrences_mixin.dart';
import 'package:analyzer_plugin/protocol/protocol.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/src/utilities/occurrences/occurrences.dart';
import 'package:analyzer_plugin/utilities/occurrences/occurrences.dart';
import 'package:path/src/context.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'mocks.dart';

void main() {
  defineReflectiveTests(OccurrencesMixinTest);
}

@reflectiveTest
class OccurrencesMixinTest {
  MemoryResourceProvider resourceProvider = new MemoryResourceProvider();

  String packagePath1;
  String filePath1;
  ContextRoot contextRoot1;

  MockChannel channel;
  _TestServerPlugin plugin;

  void setUp() {
    Context pathContext = resourceProvider.pathContext;

    packagePath1 = resourceProvider.convertPath('/package1');
    filePath1 = pathContext.join(packagePath1, 'lib', 'test.dart');
    resourceProvider.newFile(filePath1, '');
    contextRoot1 = new ContextRoot(packagePath1, <String>[]);

    channel = new MockChannel();
    plugin = new _TestServerPlugin(resourceProvider);
    plugin.start(channel);
  }

  test_sendOccurrencesNotification() async {
    await plugin.handleAnalysisSetContextRoots(
        new AnalysisSetContextRootsParams([contextRoot1]));

    Completer<void> notificationReceived = new Completer<void>();
    channel.listen(null, onNotification: (Notification notification) {
      expect(notification, isNotNull);
      AnalysisOccurrencesParams params =
          new AnalysisOccurrencesParams.fromNotification(notification);
      expect(params.file, filePath1);
      List<Occurrences> occurrenceList = params.occurrences;
      expect(occurrenceList, hasLength(3));

      void validate(String elementName, List<int> expectedOffsets) {
        for (Occurrences occurrences in occurrenceList) {
          if (occurrences.element.name == elementName) {
            expect(occurrences.offsets, expectedOffsets);
            expect(occurrences.length, elementName.length);
            return;
          }
        }
        fail('No occurence named $elementName');
      }

      validate('method', [10, 30]);
      validate('C', [20, 40, 50, 60, 70]);
      validate('local', [80]);
      notificationReceived.complete();
    });
    await plugin.sendOccurrencesNotification(filePath1);
    await notificationReceived.future;
  }
}

class _TestOccurrencesContributor implements OccurrencesContributor {
  Map<Element, List<int>> elements;

  _TestOccurrencesContributor(this.elements);

  @override
  void computeOccurrences(
      OccurrencesRequest request, OccurrencesCollector collector) {
    elements.forEach((element, offsets) {
      for (int offset in offsets) {
        collector.addOccurrence(element, offset);
      }
    });
  }
}

class _TestServerPlugin extends MockServerPlugin with OccurrencesMixin {
  _TestServerPlugin(ResourceProvider resourceProvider)
      : super(resourceProvider);

  @override
  List<OccurrencesContributor> getOccurrencesContributors(String path) {
    Element element1 = new Element(ElementKind.METHOD, 'method', 0);
    Element element2 = new Element(ElementKind.CLASS, 'C', 0);
    Element element3 = new Element(ElementKind.LOCAL_VARIABLE, 'local', 0);
    return <OccurrencesContributor>[
      new _TestOccurrencesContributor({
        element1: [10, 30],
        element2: [20, 40, 60]
      }),
      new _TestOccurrencesContributor({
        element2: [50, 70],
        element3: [80]
      })
    ];
  }

  @override
  Future<OccurrencesRequest> getOccurrencesRequest(String path) async {
    AnalysisResult result = new MockAnalysisResult(path: path);
    return new DartOccurrencesRequestImpl(resourceProvider, result);
  }
}
