// 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 analyzer.test.src.task.html_work_manager_test;

import 'package:analyzer/error/error.dart' show AnalysisError;
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/error/codes.dart' show HtmlErrorCode;
import 'package:analyzer/src/generated/engine.dart'
    show
        AnalysisEngine,
        AnalysisErrorInfo,
        AnalysisErrorInfoImpl,
        CacheState,
        ChangeNoticeImpl,
        InternalAnalysisContext;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/task/html.dart';
import 'package:analyzer/src/task/html_work_manager.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/general.dart';
import 'package:analyzer/task/html.dart';
import 'package:analyzer/task/model.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:typed_mock/typed_mock.dart';

import '../../generated/test_support.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(HtmlWorkManagerTest);
    defineReflectiveTests(HtmlWorkManagerIntegrationTest);
  });
}

@reflectiveTest
class HtmlWorkManagerTest {
  InternalAnalysisContext context = new _InternalAnalysisContextMock();
  AnalysisCache cache;
  HtmlWorkManager manager;

  CaughtException caughtException = new CaughtException(null, null);

  Source source1 = new TestSource('1.html');
  Source source2 = new TestSource('2.html');
  Source source3 = new TestSource('3.html');
  Source source4 = new TestSource('4.html');
  CacheEntry entry1;
  CacheEntry entry2;
  CacheEntry entry3;
  CacheEntry entry4;

  void expect_sourceQueue(List<Source> sources) {
    expect(manager.sourceQueue, unorderedEquals(sources));
  }

  void setUp() {
    cache = context.analysisCache;
    manager = new HtmlWorkManager(context);
    entry1 = context.getCacheEntry(source1);
    entry2 = context.getCacheEntry(source2);
    entry3 = context.getCacheEntry(source3);
    entry4 = context.getCacheEntry(source4);
  }

  void test_applyChange_add() {
    // add source1
    manager.applyChange([source1], [], []);
    expect_sourceQueue([source1]);
    // add source2
    manager.applyChange([source2], [], []);
    expect_sourceQueue([source1, source2]);
  }

  void test_applyChange_add_duplicate() {
    // add source1
    manager.applyChange([source1], [], []);
    expect_sourceQueue([source1]);
    // add source1 again
    manager.applyChange([source1], [], []);
    expect_sourceQueue([source1]);
  }

  void test_applyChange_change() {
    // change source1
    manager.applyChange([], [source1], []);
    expect_sourceQueue([source1]);
  }

  void test_applyChange_change_afterAdd() {
    manager.applyChange([source1, source2], [], []);
    // change source1
    manager.applyChange([], [source1], []);
    expect_sourceQueue([source1, source2]);
  }

  void test_applyChange_remove() {
    manager.applyChange([source1, source2], [], []);
    // remove source1
    manager.applyChange([], [], [source1]);
    expect_sourceQueue([source2]);
    // remove source2
    manager.applyChange([], [], [source2]);
    expect_sourceQueue([]);
    // remove source3
    manager.applyChange([], [], [source3]);
    expect_sourceQueue([]);
  }

  void test_applyPriorityTargets() {
    when(context.shouldErrorsBeAnalyzed(source2)).thenReturn(true);
    when(context.shouldErrorsBeAnalyzed(source3)).thenReturn(true);
    manager.priorityResultQueue.add(new TargetedResult(source1, HTML_ERRORS));
    manager.priorityResultQueue.add(new TargetedResult(source2, HTML_ERRORS));
    // -source1 +source3
    manager.applyPriorityTargets([source2, source3]);
    expect(
        manager.priorityResultQueue,
        unorderedEquals([
          new TargetedResult(source2, HTML_ERRORS),
          new TargetedResult(source3, HTML_ERRORS)
        ]));
    // get next request
    TargetedResult request = manager.getNextResult();
    expect(request.target, source2);
    expect(request.result, HTML_ERRORS);
  }

  void test_getErrors_fullList() {
    AnalysisError error1 =
        new AnalysisError(source1, 1, 0, HtmlErrorCode.PARSE_ERROR, ['']);
    AnalysisError error2 =
        new AnalysisError(source1, 2, 0, HtmlErrorCode.PARSE_ERROR, ['']);
    entry1.setValue(HTML_DOCUMENT_ERRORS, <AnalysisError>[error1], []);

    DartScript script = new DartScript(source1, []);
    entry1.setValue(DART_SCRIPTS, [script], []);
    CacheEntry scriptEntry = context.getCacheEntry(script);
    scriptEntry.setValue(DART_ERRORS, [error2], []);

    List<AnalysisError> errors = manager.getErrors(source1);
    expect(errors, unorderedEquals([error1, error2]));
  }

  void test_getErrors_partialList() {
    AnalysisError error1 =
        new AnalysisError(source1, 1, 0, HtmlErrorCode.PARSE_ERROR, ['']);
    AnalysisError error2 =
        new AnalysisError(source1, 2, 0, HtmlErrorCode.PARSE_ERROR, ['']);
    entry1.setValue(HTML_DOCUMENT_ERRORS, <AnalysisError>[error1, error2], []);

    List<AnalysisError> errors = manager.getErrors(source1);
    expect(errors, unorderedEquals([error1, error2]));
  }

  void test_getNextResult_hasNormal_firstIsError() {
    entry1.setErrorState(caughtException, [HTML_ERRORS]);
    manager.sourceQueue.addAll([source1, source2]);
    TargetedResult request = manager.getNextResult();
    expect(request.target, source2);
    expect(request.result, HTML_ERRORS);
    // source1 is out, source2 is waiting
    expect_sourceQueue([source2]);
  }

  void test_getNextResult_hasNormal_firstIsInvalid() {
    entry1.setState(HTML_ERRORS, CacheState.INVALID);
    manager.sourceQueue.addAll([source1, source2]);
    TargetedResult request = manager.getNextResult();
    expect(request.target, source1);
    expect(request.result, HTML_ERRORS);
    // no changes until computed
    expect_sourceQueue([source1, source2]);
  }

  void test_getNextResult_hasNormal_firstIsValid() {
    entry1.setValue(HTML_ERRORS, [], []);
    manager.sourceQueue.addAll([source1, source2]);
    TargetedResult request = manager.getNextResult();
    expect(request.target, source2);
    expect(request.result, HTML_ERRORS);
    // source1 is out, source2 is waiting
    expect_sourceQueue([source2]);
  }

  void test_getNextResult_hasNormalAndPriority() {
    entry1.setState(HTML_ERRORS, CacheState.INVALID);
    manager.sourceQueue.addAll([source1, source2]);
    manager.addPriorityResult(source3, HTML_ERRORS);

    TargetedResult request = manager.getNextResult();
    expect(request.target, source3);
    expect(request.result, HTML_ERRORS);
    // no changes until computed
    expect_sourceQueue([source1, source2]);
  }

  void test_getNextResult_hasPriority() {
    manager.addPriorityResult(source1, HTML_ERRORS);
    manager.addPriorityResult(source2, HTML_ERRORS);
    expect(
        manager.priorityResultQueue,
        unorderedEquals([
          new TargetedResult(source1, HTML_ERRORS),
          new TargetedResult(source2, HTML_ERRORS)
        ]));

    TargetedResult request = manager.getNextResult();
    expect(request.target, source1);
    expect(request.result, HTML_ERRORS);
    // no changes until computed
    expect(
        manager.priorityResultQueue,
        unorderedEquals([
          new TargetedResult(source1, HTML_ERRORS),
          new TargetedResult(source2, HTML_ERRORS)
        ]));
  }

  void test_getNextResult_nothingToDo() {
    TargetedResult request = manager.getNextResult();
    expect(request, isNull);
  }

  void test_getNextResultPriority_hasPriority() {
    manager.addPriorityResult(source1, SOURCE_KIND);
    expect(manager.getNextResultPriority(), WorkOrderPriority.PRIORITY);
  }

  void test_getNextResultPriority_hasSource() {
    manager.sourceQueue.addAll([source1]);
    expect(manager.getNextResultPriority(), WorkOrderPriority.NORMAL);
  }

  void test_getNextResultPriority_nothingToDo() {
    expect(manager.getNextResultPriority(), WorkOrderPriority.NONE);
  }

  void test_onAnalysisOptionsChanged() {
    when(context.exists(anyObject)).thenReturn(true);
    // set cache values
    entry1.setValue(DART_SCRIPTS, [], []);
    entry1.setValue(HTML_DOCUMENT, null, []);
    entry1.setValue(HTML_DOCUMENT_ERRORS, [], []);
    entry1.setValue(HTML_ERRORS, [], []);
    entry1.setValue(REFERENCED_LIBRARIES, [], []);
    // notify
    manager.onAnalysisOptionsChanged();
    // Only resolution-based values are invalidated.
    expect(entry1.getState(DART_SCRIPTS), CacheState.VALID);
    expect(entry1.getState(HTML_DOCUMENT), CacheState.VALID);
    expect(entry1.getState(HTML_DOCUMENT_ERRORS), CacheState.VALID);
    expect(entry1.getState(HTML_ERRORS), CacheState.INVALID);
    expect(entry1.getState(REFERENCED_LIBRARIES), CacheState.VALID);
  }

  void test_onResultInvalidated_scheduleInvalidatedLibraries() {
    // set HTML_ERRORS for source1 and source3
    entry1.setValue(HTML_ERRORS, [], []);
    entry3.setValue(HTML_ERRORS, [], []);
    // invalidate HTML_ERRORS for source1, schedule it
    entry1.setState(HTML_ERRORS, CacheState.INVALID);
    expect_sourceQueue([source1]);
    // invalidate HTML_ERRORS for source3, schedule it
    entry3.setState(HTML_ERRORS, CacheState.INVALID);
    expect_sourceQueue([source1, source3]);
  }

  void test_onSourceFactoryChanged() {
    when(context.exists(anyObject)).thenReturn(true);
    // set cache values
    entry1.setValue(DART_SCRIPTS, [], []);
    entry1.setValue(HTML_DOCUMENT, null, []);
    entry1.setValue(HTML_DOCUMENT_ERRORS, [], []);
    entry1.setValue(HTML_ERRORS, [], []);
    entry1.setValue(REFERENCED_LIBRARIES, [], []);
    // notify
    manager.onSourceFactoryChanged();
    // Only resolution-based values are invalidated.
    expect(entry1.getState(DART_SCRIPTS), CacheState.VALID);
    expect(entry1.getState(HTML_DOCUMENT), CacheState.VALID);
    expect(entry1.getState(HTML_DOCUMENT_ERRORS), CacheState.VALID);
    expect(entry1.getState(HTML_ERRORS), CacheState.INVALID);
    expect(entry1.getState(REFERENCED_LIBRARIES), CacheState.INVALID);
  }

  void test_resultsComputed_errors() {
    AnalysisError error1 =
        new AnalysisError(source1, 1, 0, HtmlErrorCode.PARSE_ERROR, ['']);
    AnalysisError error2 =
        new AnalysisError(source1, 2, 0, HtmlErrorCode.PARSE_ERROR, ['']);
    LineInfo lineInfo = new LineInfo([0]);
    entry1.setValue(LINE_INFO, lineInfo, []);
    entry1.setValue(HTML_ERRORS, <AnalysisError>[error1, error2], []);
    // RESOLVED_UNIT is ready, set errors
    manager.resultsComputed(source1, {HTML_ERRORS: null});
    // all of the errors are included
    ChangeNoticeImpl notice = context.getNotice(source1);
    expect(notice.errors, unorderedEquals([error1, error2]));
    expect(notice.lineInfo, lineInfo);
  }
}

@reflectiveTest
class HtmlWorkManagerIntegrationTest {
  InternalAnalysisContext context = new AnalysisContextImpl();
  HtmlWorkManager manager;

  Source source1 = new TestSource('1.html');
  Source source2 = new TestSource('2.html');
  CacheEntry entry1;
  CacheEntry entry2;

  void expect_sourceQueue(List<Source> sources) {
    expect(manager.sourceQueue, unorderedEquals(sources));
  }

  void setUp() {
    manager = new HtmlWorkManager(context);
    entry1 = context.getCacheEntry(source1);
    entry2 = context.getCacheEntry(source2);
  }

  void test_onResultInvalidated_scheduleInvalidatedLibrariesAfterSetSourceFactory() {
    // Change the source factory, changing the analysis cache from when
    // the work manager was constructed. This used to create a failure
    // case for test_onResultInvalidated_scheduleInvalidLibraries so its
    // tested here.
    context.sourceFactory = new _SourceFactoryMock();

    // now just do the same checks as
    // test_onResultInvalidated_scheduleInvalidLibraries

    // set HTML_ERRORS for source1 and source2
    entry1.setValue(HTML_ERRORS, [], []);
    entry2.setValue(HTML_ERRORS, [], []);
    // invalidate HTML_ERRORS for source1, schedule it
    entry1.setState(HTML_ERRORS, CacheState.INVALID);
    expect_sourceQueue([source1]);
    // invalidate HTML_ERRORS for source2, schedule it
    entry2.setState(HTML_ERRORS, CacheState.INVALID);
    expect_sourceQueue([source1, source2]);
  }

}

class _SourceFactoryMock extends TypedMock
    implements SourceFactory {
}

class _InternalAnalysisContextMock extends TypedMock
    implements InternalAnalysisContext {
  @override
  CachePartition privateAnalysisCachePartition;

  @override
  AnalysisCache analysisCache;

  // The production version is a stream that carries messages from the cache
  // since the cache changes. Here, we can just pass the inner stream because
  // it doesn't change.
  @override
  get onResultInvalidated => analysisCache.onResultInvalidated;

  Map<Source, ChangeNoticeImpl> _pendingNotices = <Source, ChangeNoticeImpl>{};

  _InternalAnalysisContextMock() {
    privateAnalysisCachePartition = new UniversalCachePartition(this);
    analysisCache = new AnalysisCache([privateAnalysisCachePartition]);
  }

  @override
  CacheEntry getCacheEntry(AnalysisTarget target) {
    CacheEntry entry = analysisCache.get(target);
    if (entry == null) {
      entry = new CacheEntry(target);
      analysisCache.put(entry);
    }
    return entry;
  }

  @override
  AnalysisErrorInfo getErrors(Source source) {
    String name = source.shortName;
    List<AnalysisError> errors = AnalysisError.NO_ERRORS;
    if (AnalysisEngine.isDartFileName(name) || source is DartScript) {
      errors = getCacheEntry(source).getValue(DART_ERRORS);
    } else if (AnalysisEngine.isHtmlFileName(name)) {
      errors = getCacheEntry(source).getValue(HTML_ERRORS);
    }
    return new AnalysisErrorInfoImpl(
        errors, getCacheEntry(source).getValue(LINE_INFO));
  }

  @override
  ChangeNoticeImpl getNotice(Source source) {
    return _pendingNotices.putIfAbsent(
        source, () => new ChangeNoticeImpl(source));
  }
}
