// 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_plugin/plugin/folding_mixin.dart';
import 'package:analyzer_plugin/plugin/plugin.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/folding/folding.dart';
import 'package:analyzer_plugin/utilities/folding/folding.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'mocks.dart';
import 'plugin_test.dart';

void main() {
  defineReflectiveTests(FoldingMixinTest);
}

@reflectiveTest
class FoldingMixinTest extends AbstractPluginTest {
  late String packagePath1;
  late String filePath1;
  late ContextRoot contextRoot1;

  @override
  ServerPlugin createPlugin() {
    return _TestServerPlugin(resourceProvider);
  }

  @override
  Future<void> setUp() async {
    await super.setUp();
    packagePath1 = convertPath('/package1');
    filePath1 = join(packagePath1, 'lib', 'test.dart');
    newFile(filePath1, '');
    contextRoot1 = ContextRoot(packagePath1, <String>[]);
  }

  Future<void> test_sendFoldingNotification() async {
    await plugin.handleAnalysisSetContextRoots(
        AnalysisSetContextRootsParams([contextRoot1]));

    var notificationReceived = Completer<void>();
    channel.listen(null, onNotification: (Notification notification) {
      expect(notification, isNotNull);
      var params = AnalysisFoldingParams.fromNotification(notification);
      expect(params.file, filePath1);
      var regions = params.regions;
      expect(regions, hasLength(7));
      notificationReceived.complete();
    });
    await plugin.sendFoldingNotification(filePath1);
    await notificationReceived.future;
  }
}

class _TestFoldingContributor implements FoldingContributor {
  int regionCount;

  _TestFoldingContributor(this.regionCount);

  @override
  void computeFolding(FoldingRequest request, FoldingCollector collector) {
    for (var i = 0; i < regionCount; i++) {
      collector.addRegion(i * 20, 10, FoldingKind.FILE_HEADER);
    }
  }
}

class _TestServerPlugin extends MockServerPlugin with FoldingMixin {
  _TestServerPlugin(super.resourceProvider);

  @override
  List<FoldingContributor> getFoldingContributors(String path) {
    return <FoldingContributor>[
      _TestFoldingContributor(3),
      _TestFoldingContributor(4)
    ];
  }

  @override
  Future<FoldingRequest> getFoldingRequest(String path) async {
    var result = MockResolvedUnitResult(path: path);
    return DartFoldingRequestImpl(resourceProvider, result);
  }
}
