// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @dart = 2.8

import 'package:file/file.dart';
import 'package:vm_service/vm_service.dart';

import '../integration.shard/test_data/basic_project.dart';
import '../integration.shard/test_data/tests_project.dart';
import '../integration.shard/test_driver.dart';
import '../integration.shard/test_utils.dart';
import '../src/common.dart';

void main() {
  group('Flutter run for web', () {
    final BasicProject project = BasicProject();
    Directory tempDir;
    FlutterRunTestDriver flutter;

    setUp(() async {
      tempDir = createResolvedTempDirectorySync('run_expression_eval_test.');
      await project.setUpIn(tempDir);
      flutter = FlutterRunTestDriver(tempDir);
    });

    tearDown(() async {
      await flutter.stop();
      tryToDelete(tempDir);
    });

    Future<void> start({bool expressionEvaluation}) async {
      // The non-test project has a loop around its breakpoints.
      // No need to start paused as all breakpoint would be eventually reached.
      await flutter.run(
        withDebugger: true, chrome: true,
        expressionEvaluation: expressionEvaluation,
        additionalCommandArgs: <String>['--verbose', '--web-renderer=html']);
    }

    Future<void> breakInBuildMethod(FlutterTestDriver flutter) async {
      await flutter.breakAt(
        project.buildMethodBreakpointUri,
        project.buildMethodBreakpointLine,
      );
    }

    Future<void> breakInTopLevelFunction(FlutterTestDriver flutter) async {
      await flutter.breakAt(
        project.topLevelFunctionBreakpointUri,
        project.topLevelFunctionBreakpointLine,
      );
    }

    testWithoutContext('cannot evaluate expression if feature is disabled', () async {
      await start(expressionEvaluation: false);
      await breakInTopLevelFunction(flutter);
      await failToEvaluateExpression(flutter);
    });

    testWithoutContext('shows no native javascript objects in static scope', () async {
      await start(expressionEvaluation: true);
      await breakInTopLevelFunction(flutter);
      await checkStaticScope(flutter);
    });

    testWithoutContext('can handle compilation errors', () async {
      await start(expressionEvaluation: true);
      await breakInTopLevelFunction(flutter);
      await evaluateErrorExpressions(flutter);
    });

    testWithoutContext('can evaluate trivial expressions in top level function', () async {
      await start(expressionEvaluation: true);
      await breakInTopLevelFunction(flutter);
      await evaluateTrivialExpressions(flutter);
    });

    testWithoutContext('can evaluate trivial expressions in build method', () async {
      await start(expressionEvaluation: true);
      await breakInBuildMethod(flutter);
      await evaluateTrivialExpressions(flutter);
    });

    testWithoutContext('can evaluate complex expressions in top level function', () async {
      await start(expressionEvaluation: true);
      await breakInTopLevelFunction(flutter);
      await evaluateComplexExpressions(flutter);
    });

    testWithoutContext('can evaluate complex expressions in build method', () async {
      await start(expressionEvaluation: true);
      await breakInBuildMethod(flutter);
      await evaluateComplexExpressions(flutter);
    });

    testWithoutContext('can evaluate trivial expressions in library without pause', () async {
      await start(expressionEvaluation: true);
      await evaluateTrivialExpressionsInLibrary(flutter);
    });

    testWithoutContext('can evaluate complex expressions in library without pause', () async {
      await start(expressionEvaluation: true);
      await evaluateComplexExpressionsInLibrary(flutter);
    });
  });

  group('Flutter test for web', () {
    final TestsProject project = TestsProject();
    Directory tempDir;
    FlutterRunTestDriver flutter;

    setUp(() async {
      tempDir = createResolvedTempDirectorySync('run_expression_eval_test.');
      await project.setUpIn(tempDir);
      flutter = FlutterRunTestDriver(tempDir);
    });

    tearDown(() async {
      await flutter.stop();
      tryToDelete(tempDir);
    });

    Future<Isolate> breakInMethod(FlutterTestDriver flutter) async {
      await flutter.addBreakpoint(
        project.breakpointAppUri,
        project.breakpointLine,
      );
      await flutter.resume();
      return flutter.waitForPause();
    }

    Future<void> startPaused({bool expressionEvaluation}) {
      // The test project does not have a loop around its breakpoints.
      // Start paused so we can set a breakpoint before passing it
      // in the execution.
      return flutter.run(
        withDebugger: true, chrome: true,
        expressionEvaluation: expressionEvaluation,
        startPaused: true, script: project.testFilePath,
        additionalCommandArgs: <String>['--verbose', '--web-renderer=html']);
    }

    testWithoutContext('cannot evaluate expressions if feature is disabled', () async {
      await startPaused(expressionEvaluation: false);
      await breakInMethod(flutter);
      await failToEvaluateExpression(flutter);
    });

    testWithoutContext('can evaluate trivial expressions in a test', () async {
      await startPaused(expressionEvaluation: true);
      await breakInMethod(flutter);
      await evaluateTrivialExpressions(flutter);
    });

    testWithoutContext('can evaluate complex expressions in a test', () async {
      await startPaused(expressionEvaluation: true);
      await breakInMethod(flutter);
      await evaluateComplexExpressions(flutter);
    });

    testWithoutContext('can evaluate trivial expressions in library without pause', () async {
      await startPaused(expressionEvaluation: true);
      await evaluateTrivialExpressionsInLibrary(flutter);
    });

    testWithoutContext('can evaluate complex expressions in library without pause', () async {
      await startPaused(expressionEvaluation: true);
      await evaluateComplexExpressionsInLibrary(flutter);
    });
  });
}

Future<void> failToEvaluateExpression(FlutterTestDriver flutter) async {
  await expectLater(
    flutter.evaluateInFrame('"test"'),
    throwsA(isA<RPCError>().having(
      (RPCError error) => error.message,
      'message',
      contains('Expression evaluation is not supported for this configuration'),
    )),
  );
}

Future<void> checkStaticScope(FlutterTestDriver flutter) async {
  final Frame res = await flutter.getTopStackFrame();
  expect(res.vars, equals(<BoundVariable>[]));
}

Future<void> evaluateErrorExpressions(FlutterTestDriver flutter) async {
  final ObjRef res = await flutter.evaluateInFrame('typo');
  expectError(res, "CompilationError: Getter not found: 'typo'.\ntypo\n^^^^");
}

Future<void> evaluateTrivialExpressions(FlutterTestDriver flutter) async {
  ObjRef res;

  res = await flutter.evaluateInFrame('"test"');
  expectInstance(res, InstanceKind.kString, 'test');

  res = await flutter.evaluateInFrame('1');
  expectInstance(res, InstanceKind.kDouble, 1.toString());

  res = await flutter.evaluateInFrame('true');
  expectInstance(res, InstanceKind.kBool, true.toString());
}

Future<void> evaluateComplexExpressions(FlutterTestDriver flutter) async {
  final ObjRef res = await flutter.evaluateInFrame('new DateTime.now().year');
  expectInstance(res, InstanceKind.kDouble, DateTime.now().year.toString());
}

Future<void> evaluateTrivialExpressionsInLibrary(FlutterTestDriver flutter) async {
  final LibraryRef library = await getRootLibrary(flutter);
  final ObjRef res = await flutter.evaluate(library.id, '"test"');
  expectInstance(res, InstanceKind.kString, 'test');
}

Future<void> evaluateComplexExpressionsInLibrary(FlutterTestDriver flutter) async {
  final LibraryRef library = await getRootLibrary(flutter);
  final ObjRef res = await flutter.evaluate(library.id, 'new DateTime.now().year');
  expectInstance(res, InstanceKind.kDouble, DateTime.now().year.toString());
}

Future<LibraryRef> getRootLibrary(FlutterTestDriver flutter) async {
  // `isolate.rootLib` returns incorrect library, so find the
  // entrypoint manually here instead.
  //
  // Issue: https://github.com/dart-lang/sdk/issues/44760
  final Isolate isolate = await flutter.getFlutterIsolate();
  return isolate.libraries
    .firstWhere((LibraryRef l) => l.uri.contains('org-dartlang-app'));
}

void expectInstance(ObjRef result, String kind, String message) {
  expect(result,
    const TypeMatcher<InstanceRef>()
      .having((InstanceRef instance) => instance.kind, 'kind', kind)
      .having((InstanceRef instance) => instance.valueAsString, 'valueAsString', message));
}

void expectError(ObjRef result, String message) {
  expect(result,
    const TypeMatcher<ErrorRef>()
      .having((ErrorRef instance) => instance.message, 'message', message));
}
