// 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.

import 'dart:io';

import 'package:dwds/src/config/tool_configuration.dart';
import 'package:dwds_test_common/test_sdk_configuration.dart';
import 'package:test/test.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<void>.delayed(const Duration(milliseconds: 100));
  }
  throw StateError('Page never initialized');
}

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

void testAll({required TestSdkConfigurationProvider provider}) {
  final context = TestContext(TestProject.test, provider);

  for (final serveFromDds in [true, false]) {
    group('Injected client with DevTools served from '
        '${serveFromDds ? 'DDS' : 'DevTools Launcher'}', () {
      setUp(() async {
        await context.setUp(
          debugSettings: TestDebugSettings.withDevToolsLaunch(
            context,
            serveFromDds: serveFromDds,
          ),
          testSettings: TestSettings(
            moduleFormat: provider.ddcModuleFormat,
            canaryFeatures: provider.canaryFeatures,
          ),
        );
        await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
        // Wait for DevTools to actually open.
        await Future<void>.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('flutter-view'));
        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<void>.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<void>.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<void>.delayed(const Duration(seconds: 2));
          windows = await context.webDriver.windows.toList();
          final devToolsWindow = windows.firstWhere(
            (Window window) => window != newAppWindow,
          );
          await devToolsWindow.setAsActive();
          expect(await context.webDriver.pageSource, contains('DevTools'));
        },
        skip: 'See https://github.com/dart-lang/webdev/issues/2462',
      );

      test(
        'destroys and recreates the isolate during a page refresh',
        () async {
          final client = context.debugConnection.vmService;
          await client.streamListen('Isolate');
          await context.makeEdits([
            (
              file: context.project.dartEntryFileName,
              originalString: 'Hello World!',
              newString: '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;
        },
        skip: 'https://github.com/dart-lang/webdev/issues/1888',
      );
    }, timeout: const Timeout.factor(2));
  }

  group('Injected client without a DevTools server', () {
    setUp(() async {
      await context.setUp(
        debugSettings: const TestDebugSettings.noDevToolsLaunch().copyWith(
          enableDevToolsLaunch: true,
          ddsConfiguration: const DartDevelopmentServiceConfiguration(
            serveDevTools: false,
          ),
        ),
        testSettings: TestSettings(
          moduleFormat: provider.ddcModuleFormat,
          canaryFeatures: provider.canaryFeatures,
        ),
      );
    });

    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<void>.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: const TestDebugSettings.noDevToolsLaunch().copyWith(
            enableDebugExtension: true,
          ),
          testSettings: TestSettings(
            moduleFormat: provider.ddcModuleFormat,
            canaryFeatures: provider.canaryFeatures,
          ),
        );
      });

      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<void>.delayed(const Duration(seconds: 2));
        final alert = context.webDriver.driver.switchTo.alert;
        expect(alert, isNotNull);
        expect(await alert.text, contains('--debug'));
        await alert.accept();
      });
    },
    tags: ['extension'],
    skip: 'https://github.com/dart-lang/webdev/issues/2114',
    timeout: const Timeout.factor(2),
  );
}
