// 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.

library test.analysis.updateContent;

import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/constants.dart';
import 'package:analysis_server/src/services/index/index.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:typed_mock/typed_mock.dart';

import '../analysis_abstract.dart';

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

compilationUnitMatcher(String file) {
  return new _ArgumentMatcher_CompilationUnit(file);
}

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

  Index createIndex() {
    return new _MockIndex();
  }

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

  test_discardNotifications_onSourceChange() async {
    createProject();
    addTestFile('');
    await server.onAnalysisComplete;
    server.setAnalysisSubscriptions({
      AnalysisService.NAVIGATION: [testFile].toSet()
    });
    // update file, analyze, but don't sent notifications
    navigationCount = 0;
    server.updateContent('1', {testFile: new AddContentOverlay('foo() {}')});
    server.test_performAllAnalysisOperations();
    expect(serverErrorCount, 0);
    expect(navigationCount, 0);
    // replace the file contents,
    // should discard any pending notification operations
    server.updateContent('2', {testFile: new AddContentOverlay('bar() {}')});
    await server.onAnalysisComplete;
    expect(serverErrorCount, 0);
    expect(navigationCount, 1);
  }

  test_illegal_ChangeContentOverlay() {
    // It should be illegal to send a ChangeContentOverlay for a file that
    // doesn't have an overlay yet.
    createProject();
    addTestFile('library foo;');
    String id = 'myId';
    try {
      server.updateContent(id, {
        testFile: new ChangeContentOverlay([new 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);
    }
  }

  test_indexUnitAfterNopChange() async {
    var testUnitMatcher = compilationUnitMatcher(testFile) as dynamic;
    createProject();
    addTestFile('main() { print(1); }');
    await server.onAnalysisComplete;
    verify(server.index.indexUnit(testUnitMatcher)).times(1);
    // add an overlay
    server.updateContent(
        '1', {testFile: new AddContentOverlay('main() { print(2); }')});
    // Perform the next single operation: analysis.
    // It will schedule an indexing operation.
    await server.test_onOperationPerformed;
    // Update the file and remove an overlay.
    resourceProvider.updateFile(testFile, 'main() { print(2); }');
    server.updateContent('2', {testFile: new RemoveContentOverlay()});
    // Validate that at the end the unit was indexed.
    await server.onAnalysisComplete;
    verify(server.index.indexUnit(testUnitMatcher)).times(3);
  }

  test_multiple_contexts() async {
    String fooPath = '/project1/foo.dart';
    resourceProvider.newFile(
        fooPath,
        '''
library foo;
import '../project2/baz.dart';
main() { f(); }''');
    String barPath = '/project2/bar.dart';
    resourceProvider.newFile(
        barPath,
        '''
library bar;
import 'baz.dart';
main() { f(); }''');
    String bazPath = '/project2/baz.dart';
    resourceProvider.newFile(
        bazPath,
        '''
library baz;
f(int i) {}
''');
    Request request =
        new AnalysisSetAnalysisRootsParams(['/project1', '/project2'], [])
            .toRequest('0');
    handleSuccessfulRequest(request);
    {
      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: new 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);
    }
  }

  test_overlay_addPreviouslyImported() async {
    Folder project = resourceProvider.newFolder('/project');
    handleSuccessfulRequest(
        new AnalysisSetAnalysisRootsParams([project.path], []).toRequest('0'));

    server.updateContent('1',
        {'/project/main.dart': new 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': new 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': []
    });
  }

  test_overlayOnly() async {
    String filePath = '/User/project1/test.dart';
    Folder folder1 = resourceProvider.newFolder('/User/project1');
    Folder folder2 = resourceProvider.newFolder('/User/project2');
    Request request =
        new AnalysisSetAnalysisRootsParams([folder1.path, folder2.path], [])
            .toRequest('0');
    handleSuccessfulRequest(request);
    // exactly 2 contexts
    expect(server.folderMap, hasLength(2));
    AnalysisContext context1 = server.folderMap[folder1];
    AnalysisContext context2 = server.folderMap[folder2];
    // no sources
    expect(_getUserSources(context1), isEmpty);
    expect(_getUserSources(context2), isEmpty);
    // add an overlay - new Source in context1
    server.updateContent('1', {filePath: new AddContentOverlay('')});
    {
      List<Source> sources = _getUserSources(context1);
      expect(sources, hasLength(1));
      expect(sources[0].fullName, filePath);
    }
    expect(_getUserSources(context2), isEmpty);
    // remove the overlay - no sources
    server.updateContent('2', {filePath: new RemoveContentOverlay()});
    expect(_getUserSources(context1), isEmpty);
    expect(_getUserSources(context2), isEmpty);
  }

  test_removeOverlay_incrementalChange() async {
    createProject();
    addTestFile('main() { print(1); }');
    await server.onAnalysisComplete;
    CompilationUnit unit = _getTestUnit();
    // add an overlay
    server.updateContent(
        '1', {testFile: new AddContentOverlay('main() { print(2); }')});
    // it was an incremental change
    await server.onAnalysisComplete;
    expect(_getTestUnit(), same(unit));
    // remove overlay
    server.updateContent('2', {testFile: new RemoveContentOverlay()});
    // it was an incremental change
    await server.onAnalysisComplete;
    expect(_getTestUnit(), same(unit));
  }

  test_sendNoticesAfterNopChange() async {
    createProject();
    addTestFile('');
    await server.onAnalysisComplete;
    // add an overlay
    server.updateContent(
        '1', {testFile: new AddContentOverlay('main() {} main() {}')});
    await server.onAnalysisComplete;
    // clear errors and make a no-op change
    filesErrors.clear();
    server.updateContent('2', {
      testFile: new ChangeContentOverlay([new SourceEdit(0, 4, 'main')])
    });
    await server.onAnalysisComplete;
    // errors should have been resent
    expect(filesErrors, isNotEmpty);
  }

  test_sendNoticesAfterNopChange_flushedUnit() async {
    createProject();
    addTestFile('');
    await server.onAnalysisComplete;
    // add an overlay
    server.updateContent(
        '1', {testFile: new AddContentOverlay('main() {} main() {}')});
    await server.onAnalysisComplete;
    // clear errors and make a no-op change
    filesErrors.clear();
    server.test_flushAstStructures(testFile);
    server.updateContent('2', {
      testFile: new ChangeContentOverlay([new SourceEdit(0, 4, 'main')])
    });
    await server.onAnalysisComplete;
    // errors should have been resent
    expect(filesErrors, isNotEmpty);
  }

  CompilationUnit _getTestUnit() {
    ContextSourcePair pair = server.getContextSourcePair(testFile);
    AnalysisContext context = pair.context;
    Source source = pair.source;
    return context.getResolvedCompilationUnit2(source, source);
  }

  List<Source> _getUserSources(AnalysisContext context) {
    List<Source> sources = <Source>[];
    context.sources.forEach((source) {
      if (source.fullName.startsWith('/User/')) {
        sources.add(source);
      }
    });
    return sources;
  }
}

class _ArgumentMatcher_CompilationUnit extends ArgumentMatcher {
  final String file;

  _ArgumentMatcher_CompilationUnit(this.file);

  @override
  bool matches(arg) {
    return arg is CompilationUnit && arg.element.source.fullName == file;
  }
}

class _MockIndex extends TypedMock implements Index {}
