// Copyright (c) 2019, 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.

@Timeout(Duration(minutes: 5))
@TestOn('vm')
import 'dart:io';

import 'package:test/test.dart';
import 'package:test_common/test_sdk_configuration.dart';
import 'package:vm_service/vm_service.dart';
// ignore: deprecated_member_use
import 'package:webdriver/io.dart';

import 'fixtures/context.dart';
import 'fixtures/project.dart';
import 'fixtures/utilities.dart';

Future<void> _waitForPageReady(TestContext context) async {
  var attempt = 100;
  while (attempt-- > 0) {
    final content = await context.webDriver.pageSource;
    if (content.contains('hello_world')) return;
    await Future.delayed(const Duration(milliseconds: 100));
  }
  throw StateError('Page never initialized');
}

void main() {
  final provider = TestSdkConfigurationProvider();
  tearDownAll(provider.dispose);

  final context = TestContext(TestProject.testWithSoundNullSafety, provider);

  group('Injected client', () {
    setUp(() async {
      await context.setUp(
        debugSettings: TestDebugSettings.withDevTools(context),
      );
      await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
      // Wait for DevTools to actually open.
      await Future.delayed(const Duration(seconds: 2));
    });

    tearDown(() async {
      await context.tearDown();
    });

    test(
      'can launch devtools',
      () async {
        final windows = await context.webDriver.windows.toList();
        await context.webDriver.driver.switchTo.window(windows.last);
        expect(await context.webDriver.pageSource, contains('DevTools'));
        expect(await context.webDriver.currentUrl, contains('ide=Dwds'));
        // TODO(https://github.com/dart-lang/webdev/issues/1888): Re-enable.
      },
      skip: Platform.isWindows,
    );

    test('can not launch devtools for the same app in multiple tabs', () async {
      final appUrl = await context.webDriver.currentUrl;
      // Open a new tab, select it, and navigate to the app
      await context.webDriver.driver
          .execute("window.open('$appUrl', '_blank');", []);
      await Future.delayed(const Duration(seconds: 2));
      final newAppWindow = await context.webDriver.windows.last;
      await newAppWindow.setAsActive();

      // Wait for the page to be ready before trying to open DevTools again.
      await _waitForPageReady(context);

      // Try to open devtools and check for the alert.
      await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
      await Future.delayed(const Duration(seconds: 2));
      final alert = context.webDriver.driver.switchTo.alert;
      expect(alert, isNotNull);
      expect(
        await alert.text,
        contains('This app is already being debugged in a different tab'),
      );
      await alert.accept();

      var windows = await context.webDriver.windows.toList();
      for (final window in windows) {
        if (window.id != newAppWindow.id) {
          await window.setAsActive();
          await window.close();
        }
      }

      await newAppWindow.setAsActive();
      await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
      await Future.delayed(const Duration(seconds: 2));
      windows = await context.webDriver.windows.toList();
      final devToolsWindow =
          windows.firstWhere((window) => window != newAppWindow);
      await devToolsWindow.setAsActive();
      expect(await context.webDriver.pageSource, contains('DevTools'));
    });

    test(
      'destroys and recreates the isolate during a page refresh',
      () async {
        // This test is the same as one in reload_test, but runs here when there
        // is a connected client (DevTools) since it can behave differently.
        // https://github.com/dart-lang/webdev/pull/901#issuecomment-586438132
        final client = context.debugConnection.vmService;
        await client.streamListen('Isolate');
        context.makeEditToDartEntryFile(
          toReplace: 'Hello World!',
          replaceWith: 'Bonjour le monde!',
        );
        await context.waitForSuccessfulBuild(propagateToBrowser: true);

        final eventsDone = expectLater(
          client.onIsolateEvent,
          emitsThrough(
            emitsInOrder([
              _hasKind(EventKind.kIsolateExit),
              _hasKind(EventKind.kIsolateStart),
              _hasKind(EventKind.kIsolateRunnable),
            ]),
          ),
        );

        await context.webDriver.driver.refresh();

        await eventsDone;
        // Re-set the edited file:
        context.makeEditToDartEntryFile(
          toReplace: 'Bonjour le monde!',
          replaceWith: 'Hello World!',
        );
      },
      skip: 'https://github.com/dart-lang/webdev/issues/1888',
    );
  });

  group('Injected client without a DevTools server', () {
    setUp(() async {
      await context.setUp(
        debugSettings: TestDebugSettings.noDevTools().copyWith(
          enableDevToolsLaunch: true,
        ),
      );
    });

    tearDown(() async {
      await context.tearDown();
    });

    test('gives a good error if devtools is not served', () async {
      // Try to open devtools and check for the alert.
      await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
      await Future.delayed(const Duration(seconds: 2));
      final alert = context.webDriver.driver.switchTo.alert;
      expect(alert, isNotNull);
      expect(await alert.text, contains('--debug'));
      await alert.accept();
    });
  });

  group(
    'Injected client with debug extension and without DevTools',
    () {
      setUp(() async {
        await context.setUp(
          debugSettings: TestDebugSettings.noDevTools()
              .copyWith(enableDebugExtension: true),
        );
      });

      tearDown(() async {
        await context.tearDown();
      });

      test('gives a good error if devtools is not served', () async {
        // Click on extension
        await context.extensionConnection.sendCommand('Runtime.evaluate', {
          'expression': 'fakeClick()',
        });
        // Try to open devtools and check for the alert.
        await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
        await Future.delayed(const Duration(seconds: 2));
        final alert = context.webDriver.driver.switchTo.alert;
        expect(alert, isNotNull);
        expect(await alert.text, contains('--debug'));
        await alert.accept();
      });
      // TODO(https://github.com/dart-lang/webdev/issues/1724): Re-enable debug
      // extension tests on Windows.
    },
    tags: ['extension'],
    skip: 'https://github.com/dart-lang/webdev/issues/2114',
  );
}

TypeMatcher<Event> _hasKind(String kind) =>
    isA<Event>().having((e) => e.kind, 'kind', kind);
