// 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: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(Uri.parse('file:///'));

  /// The object under test.
  IncrementalResolvedAstGenerator incrementalResolvedAstGenerator;

  Future<Map<Uri, Map<Uri, CompilationUnit>>> 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][fooUri], 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][fooUri], 1);
    incrementalResolvedAstGenerator.invalidateAll();
    var deltaProgram2 = await incrementalResolvedAstGenerator.computeDelta();
    expect(deltaProgram2.newState.keys, unorderedEquals([fooUri]));
    _checkMain(deltaProgram2.newState[fooUri][fooUri], 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].keys, unorderedEquals([fooUri, barUri]));
    var mainStatements = _getFunctionStatements(
        _getFunction(initialProgram[fooUri][fooUri], 'main'));
    var fDeclaration = _getFunction(initialProgram[fooUri][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;
  }
}
