// 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/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:front_end/compiler_options.dart';
import 'package:front_end/incremental_resolved_ast_generator.dart';
import 'package:front_end/memory_file_system.dart';
import 'package:path/path.dart' as pathos;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

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

final _sdkSummary = _readSdkSummary();

List<int> _readSdkSummary() {
  var resourceProvider = PhysicalResourceProvider.INSTANCE;
  var sdk = new FolderBasedDartSdk(resourceProvider,
      FolderBasedDartSdk.defaultSdkDirectory(resourceProvider))
    ..useSummary = true;
  var path = resourceProvider.pathContext
      .join(sdk.directory.path, 'lib', '_internal', 'strong.sum');
  return resourceProvider.getFile(path).readAsBytesSync();
}

@reflectiveTest
class IncrementalResolvedAstGeneratorTest {
  static final sdkSummaryUri = Uri.parse('special:sdk_summary');

  /// Virtual filesystem for testing.
  final fileSystem = new MemoryFileSystem(pathos.posix, Uri.parse('file:///'));

  /// The object under test.
  IncrementalResolvedAstGenerator incrementalResolvedAstGenerator;

  Future<Map<Uri, ResolvedLibrary>> getInitialProgram(Uri startingUri) async {
    fileSystem.entityForUri(sdkSummaryUri).writeAsBytesSync(_sdkSummary);
    incrementalResolvedAstGenerator = new IncrementalResolvedAstGenerator(
        startingUri,
        new CompilerOptions()
          ..fileSystem = fileSystem
          ..chaseDependencies = true
          ..sdkSummary = sdkSummaryUri
          ..packagesFileUri = new Uri());
    return (await incrementalResolvedAstGenerator.computeDelta()).newState;
  }

  test_incrementalUpdate_referenceToCore() async {
    writeFiles({'/foo.dart': 'main() { print(1); }'});
    var fooUri = Uri.parse('file:///foo.dart');
    var initialProgram = await getInitialProgram(fooUri);
    expect(initialProgram.keys, unorderedEquals([fooUri]));

    void _checkMain(CompilationUnit unit, int expectedArgument) {
      var mainStatements = _getFunctionStatements(_getFunction(unit, 'main'));
      expect(mainStatements, hasLength(1));
      _checkPrintLiteralInt(mainStatements[0], expectedArgument);
    }

    _checkMain(initialProgram[fooUri].definingCompilationUnit, 1);
    writeFiles({'/foo.dart': 'main() { print(2); }'});
    // Verify that the file isn't actually reread until invalidate is called.
    var deltaProgram1 = await incrementalResolvedAstGenerator.computeDelta();
    // TODO(paulberry): since there is no delta, computeDelta should return an
    // empty map.
    // expect(deltaProgram1.newState, isEmpty);
    expect(deltaProgram1.newState.keys, unorderedEquals([fooUri]));
    _checkMain(deltaProgram1.newState[fooUri].definingCompilationUnit, 1);
    incrementalResolvedAstGenerator.invalidateAll();
    var deltaProgram2 = await incrementalResolvedAstGenerator.computeDelta();
    expect(deltaProgram2.newState.keys, unorderedEquals([fooUri]));
    _checkMain(deltaProgram2.newState[fooUri].definingCompilationUnit, 2);
  }

  test_invalidateAllBeforeInitialProgram() async {
    incrementalResolvedAstGenerator = new IncrementalResolvedAstGenerator(
        Uri.parse('file:///foo.dart'),
        new CompilerOptions()
          ..fileSystem = fileSystem
          ..chaseDependencies = true
          ..packagesFileUri = new Uri());
    incrementalResolvedAstGenerator.invalidateAll();
  }

  test_part() async {
    writeFiles({
      '/foo.dart': 'library foo; part "bar.dart"; main() { print(1); f(); }',
      '/bar.dart': 'part of foo; f() { print(2); }'
    });
    var fooUri = Uri.parse('file:///foo.dart');
    var barUri = Uri.parse('file:///bar.dart');
    var initialProgram = await getInitialProgram(fooUri);
    expect(initialProgram.keys, unorderedEquals([fooUri]));
    expect(initialProgram[fooUri].partUnits.keys, unorderedEquals([barUri]));
    var mainStatements = _getFunctionStatements(
        _getFunction(initialProgram[fooUri].definingCompilationUnit, 'main'));
    var fDeclaration =
        _getFunction(initialProgram[fooUri].partUnits[barUri], 'f');
    var fStatements = _getFunctionStatements(fDeclaration);
    expect(mainStatements, hasLength(2));
    _checkPrintLiteralInt(mainStatements[0], 1);
    _checkFunctionCall(mainStatements[1],
        resolutionMap.elementDeclaredByFunctionDeclaration(fDeclaration));
    expect(fStatements, hasLength(1));
    _checkPrintLiteralInt(fStatements[0], 2);
    // TODO(paulberry): now test incremental updates
  }

  /// Write the given file contents to the virtual filesystem.
  void writeFiles(Map<String, String> contents) {
    contents.forEach((path, text) {
      fileSystem
          .entityForUri(Uri.parse('file://$path'))
          .writeAsStringSync(text);
    });
  }

  void _checkFunctionCall(Statement statement, Element expectedTarget) {
    expect(statement, new isInstanceOf<ExpressionStatement>());
    var expressionStatement = statement as ExpressionStatement;
    expect(
        expressionStatement.expression, new isInstanceOf<MethodInvocation>());
    var methodInvocation = expressionStatement.expression as MethodInvocation;
    expect(
        resolutionMap.staticElementForIdentifier(methodInvocation.methodName),
        expectedTarget);
  }

  void _checkPrintLiteralInt(Statement statement, int expectedArgument) {
    expect(statement, new isInstanceOf<ExpressionStatement>());
    var expressionStatement = statement as ExpressionStatement;
    expect(
        expressionStatement.expression, new isInstanceOf<MethodInvocation>());
    var methodInvocation = expressionStatement.expression as MethodInvocation;
    expect(methodInvocation.methodName.name, 'print');
    var printElement =
        resolutionMap.staticElementForIdentifier(methodInvocation.methodName);
    expect(printElement, isNotNull);
    expect(printElement.library.source.uri, Uri.parse('dart:core'));
    expect(methodInvocation.argumentList.arguments, hasLength(1));
    expect(methodInvocation.argumentList.arguments[0],
        new isInstanceOf<IntegerLiteral>());
    var integerLiteral =
        methodInvocation.argumentList.arguments[0] as IntegerLiteral;
    expect(integerLiteral.value, expectedArgument);
  }

  FunctionDeclaration _getFunction(CompilationUnit unit, String name) {
    for (var declaration in unit.declarations) {
      if (declaration is FunctionDeclaration && declaration.name.name == name) {
        return declaration;
      }
    }
    throw fail('No function declaration found with name "$name"');
  }

  NodeList<Statement> _getFunctionStatements(FunctionDeclaration function) {
    var body = function.functionExpression.body;
    expect(body, new isInstanceOf<BlockFunctionBody>());
    return (body as BlockFunctionBody).block.statements;
  }
}
