// Copyright (c) 2015, 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 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../analysis_abstract.dart';
import '../mocks.dart';

void main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(UpdateContentTest);
  });
}

@reflectiveTest
class UpdateContentTest extends AbstractAnalysisTest {
  Map<String, List<String>> filesErrors = {};
  int serverErrorCount = 0;
  int navigationCount = 0;

  @override
  void processNotification(Notification notification) {
    if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
      var decoded = AnalysisErrorsParams.fromNotification(notification);
      String _format(AnalysisError e) =>
          '${e.location.startLine}: ${e.message}';
      filesErrors[decoded.file] = decoded.errors.map(_format).toList();
    }
    if (notification.event == ANALYSIS_NOTIFICATION_NAVIGATION) {
      navigationCount++;
    }
    if (notification.event == SERVER_NOTIFICATION_ERROR) {
      serverErrorCount++;
    }
  }

  void test_illegal_ChangeContentOverlay() async {
    // It should be illegal to send a ChangeContentOverlay for a file that
    // doesn't have an overlay yet.
    await createProject();
    addTestFile('library foo;');
    var id = 'myId';
    try {
      server.updateContent(id, {
        testFile: ChangeContentOverlay([SourceEdit(8, 3, 'bar')])
      });
      fail('Expected an exception to be thrown');
    } on RequestFailure catch (e) {
      expect(e.response.id, id);
      expect(e.response.error!.code, RequestErrorCode.INVALID_OVERLAY_CHANGE);
    }
  }

  Future<void> test_invalidFilePathFormat_notAbsolute() async {
    var request = AnalysisUpdateContentParams(
      {'test.dart': AddContentOverlay('')},
    ).toRequest('0');
    var response = await waitResponse(request);
    expect(
      response,
      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
    );
  }

  Future<void> test_invalidFilePathFormat_notNormalized() async {
    var request = AnalysisUpdateContentParams(
      {convertPath('/foo/../bar/test.dart'): AddContentOverlay('')},
    ).toRequest('0');
    var response = await waitResponse(request);
    expect(
      response,
      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
    );
  }

  Future<void> test_multiple_contexts() async {
    var project1path = convertPath('/project1');
    var project2path = convertPath('/project2');
    var fooPath = newFile('/project1/foo.dart', content: '''
library foo;
import '../project2/baz.dart';
main() { f(); }''').path;
    var barPath = newFile('/project2/bar.dart', content: '''
library bar;
import 'baz.dart';
main() { f(); }''').path;
    var bazPath = newFile('/project2/baz.dart', content: '''
library baz;
f(int i) {}
''').path;
    await setRoots(included: [project1path, project2path], excluded: []);
    {
      await server.onAnalysisComplete;
      // Files foo.dart and bar.dart should both have errors, since they both
      // call f() with the wrong number of arguments.
      expect(filesErrors[fooPath], hasLength(1));
      expect(filesErrors[barPath], hasLength(1));
      // Overlay the content of baz.dart to eliminate the errors.
      server.updateContent('1', {
        bazPath: AddContentOverlay('''
library baz;
f() {}
''')
      });
    }
    {
      await server.onAnalysisComplete;
      // The overlay should have been propagated to both contexts, causing both
      // foo.dart and bar.dart to be reanalyzed and found to be free of errors.
      expect(filesErrors[fooPath], isEmpty);
      expect(filesErrors[barPath], isEmpty);
    }
  }

  @failingTest
  Future<void> test_overlay_addPreviouslyImported() async {
    // The list of errors doesn't include errors for '/project/target.dart'.
    var project = newFolder('/project');
    await setRoots(included: [project.path], excluded: []);

    server.updateContent('1',
        {'/project/main.dart': AddContentOverlay('import "target.dart";')});
    await server.onAnalysisComplete;
    expect(filesErrors, {
      '/project/main.dart': ["1: Target of URI doesn't exist: 'target.dart'."],
      '/project/target.dart': []
    });

    server.updateContent('1',
        {'/project/target.dart': AddContentOverlay('import "none.dart";')});
    await server.onAnalysisComplete;
    expect(filesErrors, {
      '/project/main.dart': ['1: Unused import.'],
      '/project/target.dart': ["1: Target of URI doesn't exist: 'none.dart'."],
      '/project/none.dart': []
    });
  }

  Future<void> test_overlayOnly() async {
    var filePath1 = convertPath('/User/project1/test.dart');
    var filePath2 = convertPath('/User/project2/test.dart');
    var folderPath1 = newFolder('/User/project1').path;
    var folderPath2 = newFolder('/User/project2').path;

    await setRoots(included: [folderPath1, folderPath2], excluded: []);

    // exactly 2 contexts
    expect(server.driverMap, hasLength(2));
    var driver1 = server.getAnalysisDriver(filePath1)!;
    var driver2 = server.getAnalysisDriver(filePath2)!;

    // no sources
    expect(_getUserSources(driver1), isEmpty);
    expect(_getUserSources(driver2), isEmpty);

    // add an overlay - new Source in context1
    server.updateContent('1', {filePath1: AddContentOverlay('')});
    expect(_getUserSources(driver1), [filePath1]);
    expect(_getUserSources(driver2), isEmpty);

    // remove the overlay - no sources
    server.updateContent('2', {filePath1: RemoveContentOverlay()});

    // The file isn't removed from the list of added sources.
//    expect(_getUserSources(driver1), isEmpty);
    expect(_getUserSources(driver2), isEmpty);
  }

  @failingTest
  Future<void> test_sendNoticesAfterNopChange() async {
    // The errors are empty on the last line.
    addTestFile('');
    await createProject();
    await server.onAnalysisComplete;
    // add an overlay
    server.updateContent(
        '1', {testFile: AddContentOverlay('main() {} main() {}')});
    await server.onAnalysisComplete;
    // clear errors and make a no-op change
    filesErrors.clear();
    server.updateContent('2', {
      testFile: ChangeContentOverlay([SourceEdit(0, 4, 'main')])
    });
    await server.onAnalysisComplete;
    // errors should have been resent
    expect(filesErrors, isNotEmpty);
  }

  @failingTest
  Future<void> test_sendNoticesAfterNopChange_flushedUnit() async {
    // The list of errors is empty on the last line.
    addTestFile('');
    await createProject();
    await server.onAnalysisComplete;
    // add an overlay
    server.updateContent(
        '1', {testFile: AddContentOverlay('main() {} main() {}')});
    await server.onAnalysisComplete;
    // clear errors and make a no-op change
    filesErrors.clear();
    server.updateContent('2', {
      testFile: ChangeContentOverlay([SourceEdit(0, 4, 'main')])
    });
    await server.onAnalysisComplete;
    // errors should have been resent
    expect(filesErrors, isNotEmpty);
  }

  void test_sentToPlugins() {
    var filePath = convertPath('/project/target.dart');
    var fileContent = 'import "none.dart";';
    //
    // Add
    //
    handleSuccessfulRequest(AnalysisUpdateContentParams(
            <String, Object>{filePath: AddContentOverlay(fileContent)})
        .toRequest('0'));
    var params = pluginManager.analysisUpdateContentParams!;
    var files = params.files;
    expect(files, hasLength(1));
    var overlay = files[filePath];
    expect(overlay, const TypeMatcher<AddContentOverlay>());
    var addOverlay = overlay as AddContentOverlay;
    expect(addOverlay.content, fileContent);
    //
    // Change
    //
    pluginManager.analysisUpdateContentParams = null;
    handleSuccessfulRequest(AnalysisUpdateContentParams(<String, Object>{
      filePath: ChangeContentOverlay(
          <SourceEdit>[SourceEdit(8, 1, "'"), SourceEdit(18, 1, "'")])
    }).toRequest('1'));
    params = pluginManager.analysisUpdateContentParams!;
    expect(params, isNotNull);
    files = params.files;
    expect(files, hasLength(1));
    overlay = files[filePath];
    expect(overlay, const TypeMatcher<ChangeContentOverlay>());
    var changeOverlay = overlay as ChangeContentOverlay;
    expect(changeOverlay.edits, hasLength(2));
    //
    // Remove
    //
    pluginManager.analysisUpdateContentParams = null;
    handleSuccessfulRequest(AnalysisUpdateContentParams(
        <String, Object>{filePath: RemoveContentOverlay()}).toRequest('2'));
    params = pluginManager.analysisUpdateContentParams!;
    expect(params, isNotNull);
    files = params.files;
    expect(files, hasLength(1));
    overlay = files[filePath];
    expect(overlay, const TypeMatcher<RemoveContentOverlay>());
  }

  List<String> _getUserSources(AnalysisDriver driver) {
    var sources = <String>[];
    driver.addedFiles.forEach((path) {
      if (path.startsWith(convertPath('/User/'))) {
        sources.add(path);
      }
    });
    return sources;
  }
}
