// 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/file_system/file_system.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:typed_mock/typed_mock.dart';
import 'package:unittest/unittest.dart';

import '../analysis_abstract.dart';
import '../utils.dart';

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

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

@reflectiveTest
class UpdateContentTest extends AbstractAnalysisTest {
  Map<String, List<AnalysisError>> 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);
      filesErrors[decoded.file] = decoded.errors;
    }
    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.index(anyObject, 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.index(anyObject, 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_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 {}
