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

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;

import 'package:image/image.dart';
import 'package:path/path.dart' as path;
import 'package:test_api/src/backend/runtime.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
    as wip;

import 'browser.dart';
import 'browser_lock.dart';
import 'browser_process.dart';
import 'chrome_installer.dart';
import 'common.dart';
import 'environment.dart';

/// Provides an environment for desktop Chrome.
class ChromeEnvironment implements BrowserEnvironment {
  ChromeEnvironment({
    required bool enableWasmGC,
    required bool useDwarf,
  }) : _enableWasmGC = enableWasmGC,
       _useDwarf = useDwarf;

  late final BrowserInstallation _installation;

  final bool _enableWasmGC;
  final bool _useDwarf;

  @override
  Future<Browser> launchBrowserInstance(
    Uri url, {
    bool debug = false,
  }) async {
    return Chrome(
      url,
      _installation,
      debug: debug,
      enableWasmGC: _enableWasmGC,
      useDwarf: _useDwarf
    );
  }

  @override
  Runtime get packageTestRuntime => Runtime.chrome;

  @override
  Future<void> prepare() async {
    final String version = browserLock.chromeLock.versionForCurrentPlatform;
    _installation = await getOrInstallChrome(
      version,
      infoLog: isCi ? stdout : DevNull(),
    );
  }

  @override
  Future<void> cleanup() async {}

  @override
  String get packageTestConfigurationYamlFile => 'dart_test_chrome.yaml';

  @override
  final String name = 'Chrome';
}

/// Runs desktop Chrome.
///
/// Most of the communication with the browser is expected to happen via HTTP,
/// so this exposes a bare-bones API. The browser starts as soon as the class is
/// constructed, and is killed when [close] is called.
///
/// Any errors starting or running the process are reported through [onExit].
class Chrome extends Browser {
  /// Starts a new instance of Chrome open to the given [url], which may be a
  /// [Uri] or a [String].
  factory Chrome(
    Uri url,
    BrowserInstallation installation, {
    required bool debug,
    required bool enableWasmGC,
    required bool useDwarf,
  }) {
    final Completer<Uri> remoteDebuggerCompleter = Completer<Uri>.sync();
    return Chrome._(BrowserProcess(() async {
      // A good source of various Chrome CLI options:
      // https://peter.sh/experiments/chromium-command-line-switches/
      //
      // Things to try:
      // --font-render-hinting
      // --enable-font-antialiasing
      // --gpu-rasterization-msaa-sample-count
      // --disable-gpu
      // --disallow-non-exact-resource-reuse
      // --disable-font-subpixel-positioning
      final bool isChromeNoSandbox =
          Platform.environment['CHROME_NO_SANDBOX'] == 'true';
      final String dir = await generateUserDirectory(installation, useDwarf);
      final String jsFlags = enableWasmGC ? <String>[
        '--experimental-wasm-gc',
        '--experimental-wasm-stack-switching',
        '--experimental-wasm-type-reflection',
      ].join(' ') : '';
      final List<String> args = <String>[
        if (jsFlags.isNotEmpty) '--js-flags=$jsFlags',
        '--user-data-dir=$dir',
        url.toString(),
        if (!debug)
          '--headless',
        if (isChromeNoSandbox)
          '--no-sandbox',
        // When headless, this is the actual size of the viewport.
        if (!debug)
          '--window-size=$kMaxScreenshotWidth,$kMaxScreenshotHeight',
        // When debugging, run in maximized mode so there's enough room for DevTools.
        if (debug)
          '--start-maximized',
        if (debug)
          '--auto-open-devtools-for-tabs',
        if (useDwarf)
          '--devtools-flags=enabledExperiments=wasmDWARFDebugging',
        // Always run unit tests at a 1x scale factor
        '--force-device-scale-factor=1',
        if (!useDwarf)
          // DWARF debugging requires a Chrome extension.
          '--disable-extensions',
        '--disable-popup-blocking',
        // Indicates that the browser is in "browse without sign-in" (Guest session) mode.
        '--bwsi',
        '--no-first-run',
        '--no-default-browser-check',
        '--disable-default-apps',
        '--disable-translate',
        '--remote-debugging-port=$kDevtoolsPort',

        // SwiftShader support on ARM macs is disabled until they upgrade to a newer
        // version of LLVM, see https://issuetracker.google.com/issues/165000222. In
        // headless Chrome, the default is to use SwiftShader as a software renderer
        // for WebGL contexts. In order to work around this limitation, we can force
        // GPU rendering with this flag.
        if (environment.isMacosArm)
          '--use-angle=metal',
      ];

      final Process process =
          await _spawnChromiumProcess(installation.executable, args);

      remoteDebuggerCompleter.complete(
          getRemoteDebuggerUrl(Uri.parse('http://localhost:$kDevtoolsPort')));

      unawaited(process.exitCode
          .then((_) => Directory(dir).deleteSync(recursive: true)));

      return process;
    }), remoteDebuggerCompleter.future);
  }

  Chrome._(this._process, this.remoteDebuggerUrl);

  static Future<String> generateUserDirectory(
    BrowserInstallation installation,
    bool useDwarf
  ) async {
    final String userDirectoryPath = environment
        .webUiDartToolDir
        .createTempSync('test_chrome_user_data_')
        .resolveSymbolicLinksSync();
    if (!useDwarf) {
      return userDirectoryPath;
    }

    // Using DWARF debugging info requires installation of a Chrome extension.
    // We can prompt for this, but in order to avoid prompting on every single
    // browser launch, we cache the user directory after it has been installed.
    final Directory baselineUserDirectory = Directory(path.join(
      environment.webUiDartToolDir.path,
      'chrome_user_data_base',
    ));
    final Directory dwarfExtensionInstallDirectory = Directory(path.join(
      baselineUserDirectory.path,
      'Default',
      'Extensions',
      // This is the ID of the dwarf debugging extension.
      'pdcpmagijalfljmkmjngeonclgbbannb',
    ));
    if (!baselineUserDirectory.existsSync()) {
      baselineUserDirectory.createSync(recursive: true);
    }
    if (!dwarfExtensionInstallDirectory.existsSync()) {
      print('DWARF debugging requested. Launching Chrome. Please install the '
            'extension and then exit Chrome when the installation is complete...');
      final Process addExtension = await Process.start(
        installation.executable,
        <String>[
          '--user-data-dir=${baselineUserDirectory.path}',
          'https://goo.gle/wasm-debugging-extension',
          '--bwsi',
          '--no-first-run',
          '--no-default-browser-check',
          '--disable-default-apps',
          '--disable-translate',
        ]
      );
      await addExtension.exitCode;
    }
    for (final FileSystemEntity input in baselineUserDirectory.listSync(recursive: true)) {
      final String relative = path.relative(input.path, from: baselineUserDirectory.path);
      final String outputPath = path.join(userDirectoryPath, relative);
      if (input is Directory) {
        await Directory(outputPath).create(recursive: true);
      } else if (input is File) {
        await input.copy(outputPath);
      }
    }
    return userDirectoryPath;
  }

  final BrowserProcess _process;

  @override
  final Future<Uri> remoteDebuggerUrl;

  @override
  Future<void> get onExit => _process.onExit;

  @override
  Future<void> close() => _process.close();

  // Always compare screenshots when running tests locally. On CI only compare
  // on Linux.
  @override
  bool get supportsScreenshots => Platform.isLinux || !isLuci;

  /// Capture a screenshot of the web content.
  ///
  /// Uses Webkit Inspection Protocol server's `captureScreenshot` API.
  ///
  /// [region] is used to decide which part of the web content will be used in
  /// test image. It includes starting coordinate x,y as well as height and
  /// width of the area to capture.
  ///
  /// This method can be used for both macOS and Linux.
  // TODO(yjbanov): extends tests to Window, https://github.com/flutter/flutter/issues/65673
  @override
  Future<Image> captureScreenshot(math.Rectangle<num>? region) async {
    final wip.ChromeConnection chromeConnection =
        wip.ChromeConnection('localhost', kDevtoolsPort);
    final wip.ChromeTab? chromeTab = await chromeConnection.getTab(
        (wip.ChromeTab chromeTab) => chromeTab.url.contains('localhost'));
    if (chromeTab == null) {
      throw StateError(
        'Failed locate Chrome tab with the test page',
      );
    }
    final wip.WipConnection wipConnection = await chromeTab.connect();

    Map<String, dynamic>? captureScreenshotParameters;
    if (region != null) {
      captureScreenshotParameters = <String, dynamic>{
        'format': 'png',
        'clip': <String, dynamic>{
          'x': region.left,
          'y': region.top,
          'width': region.width,
          'height': region.height,
          'scale':
              // This is NOT the DPI of the page, instead it's the "zoom level".
              1,
        },
      };
    }

    // Setting hardware-independent screen parameters:
    // https://chromedevtools.github.io/devtools-protocol/tot/Emulation
    await wipConnection
        .sendCommand('Emulation.setDeviceMetricsOverride', <String, dynamic>{
      'width': kMaxScreenshotWidth,
      'height': kMaxScreenshotHeight,
      'deviceScaleFactor': 1,
      'mobile': false,
    });
    final wip.WipResponse response = await wipConnection.sendCommand(
        'Page.captureScreenshot', captureScreenshotParameters);

    final Image screenshot =
        decodePng(base64.decode(response.result!['data'] as String))!;

    return screenshot;
  }

}

/// Used by [Chrome] to detect a glibc bug and retry launching the
/// browser.
///
/// Once every few thousands of launches we hit this glibc bug:
///
/// https://sourceware.org/bugzilla/show_bug.cgi?id=19329.
///
/// When this happens Chrome spits out something like the following then exits with code 127:
///
///     Inconsistency detected by ld.so: ../elf/dl-tls.c: 493: _dl_allocate_tls_init: Assertion `listp->slotinfo[cnt].gen <= GL(dl_tls_generation)' failed!
const String _kGlibcError = 'Inconsistency detected by ld.so';

Future<Process> _spawnChromiumProcess(String executable, List<String> args, { String? workingDirectory }) async {
  // Keep attempting to launch the browser until one of:
  // - Chrome launched successfully, in which case we just return from the loop.
  // - The tool detected an unretriable Chrome error, in which case we throw ToolExit.
  while (true) {
    final Process process = await Process.start(executable, args, workingDirectory: workingDirectory);

    process.stdout
      .transform(utf8.decoder)
      .transform(const LineSplitter())
      .listen((String line) {
        print('[CHROME STDOUT]: $line');
      });

    // Wait until the DevTools are listening before trying to connect. This is
    // only required for flutter_test --platform=chrome and not flutter run.
    bool hitGlibcBug = false;
    await process.stderr
      .transform(utf8.decoder)
      .transform(const LineSplitter())
      .map((String line) {
        print('[CHROME STDERR]:$line');
        if (line.contains(_kGlibcError)) {
          hitGlibcBug = true;
        }
        return line;
      })
      .firstWhere((String line) => line.startsWith('DevTools listening'), orElse: () {
        if (hitGlibcBug) {
          const String message = 'Encountered glibc bug '
              'https://sourceware.org/bugzilla/show_bug.cgi?id=19329. '
              'Will try launching browser again.';
          print(message);
          return message;
        }
        print('Failed to launch browser. Command used to launch it: ${args.join(' ')}');
        throw Exception(
          'Failed to launch browser. Make sure you are using an up-to-date '
          'Chrome or Edge. Otherwise, consider using -d web-server instead '
          'and filing an issue at https://github.com/flutter/flutter/issues.',
        );
      });

    if (!hitGlibcBug) {
      return process;
    }

    // A precaution that avoids accumulating browser processes, in case the
    // glibc bug doesn't cause the browser to quit and we keep looping and
    // launching more processes.

    // It's OK to not await the future here, as this is a best-effort process
    // clean-up only. If we're executing this line, this means things are off
    // the rails already due to the glibc bug, and we're just scrambling to keep
    // the system stable.
    // ignore: unawaited_futures
    process.exitCode.timeout(const Duration(seconds: 1), onTimeout: () {
      process.kill();
      return -1;
    });
  }
}

/// Returns the full URL of the Chrome remote debugger for the main page.
///
/// This takes the [base] remote debugger URL (which points to a browser-wide
/// page) and uses its JSON API to find the resolved URL for debugging the host
/// page.
Future<Uri> getRemoteDebuggerUrl(Uri base) async {
  try {
    final HttpClient client = HttpClient();
    final HttpClientRequest request = await client.getUrl(base.resolve('/json/list'));
    final HttpClientResponse response = await request.close();
    final List<dynamic>? jsonObject =
        await json.fuse(utf8).decoder.bind(response).single as List<dynamic>?;
    return base.resolve((jsonObject!.first as Map<dynamic, dynamic>)['devtoolsFrontendUrl'] as String);
  } catch (_) {
    // If we fail to talk to the remote debugger protocol, give up and return
    // the raw URL rather than crashing.
    return base;
  }
}
