// 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:io' as 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 'browser.dart';
import 'browser_lock.dart';
import 'environment.dart';
import 'safari_installation.dart';
import 'utils.dart';

/// Provides an environment for the mobile variant of Safari running in an iOS
/// simulator.
class SafariIosEnvironment implements BrowserEnvironment {
  @override
  Browser launchBrowserInstance(Uri url, {bool debug = false}) {
    return SafariIos(url);
  }

  @override
  Runtime get packageTestRuntime => Runtime.safari;

  @override
  Future<void> prepare() async {
    await initIosSimulator();
  }

  @override
  ScreenshotManager? getScreenshotManager() {
    return SafariIosScreenshotManager();
  }

  @override
  String get packageTestConfigurationYamlFile => 'dart_test_safari.yaml';
}

/// Runs an instance of Safari for iOS (i.e. mobile Safari).
///
/// 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 SafariIos extends Browser {
  @override
  final String name = 'Safari iOS';

  /// Starts a new instance of Safari open to the given [url], which may be a
  /// [Uri].
  factory SafariIos(Uri url) {
    return SafariIos._(() async {
      // iOS-Safari
      // Uses `xcrun simctl`. It is a command line utility to control the
      // Simulator. For more details on interacting with the simulator:
      // https://developer.apple.com/library/archive/documentation/IDEs/Conceptual/iOS_Simulator_Guide/InteractingwiththeiOSSimulator/InteractingwiththeiOSSimulator.html
      final io.Process process = await io.Process.start('xcrun', <String>[
        'simctl',
        'openurl', // Opens the url on Safari installed on the simulator.
        'booted', // The simulator is already booted.
        url.toString(),
      ]);

      return process;
    });
  }

  SafariIos._(Future<io.Process> Function() startBrowser) : super(startBrowser);
}

/// [ScreenshotManager] implementation for Safari.
///
/// This manager will only be created/used for macOS.
class SafariIosScreenshotManager extends ScreenshotManager {
  @override
  String get filenameSuffix => '.iOS_Safari';

  SafariIosScreenshotManager() {
    final SafariIosLock lock = browserLock.safariIosLock;
    _heightOfHeader = lock.heightOfHeader;
    _heightOfFooter = lock.heightOfFooter;
    _scaleFactor = lock.scaleFactor;

    /// Create the directory to use for taking screenshots, if it does not
    /// exists.
    if (!environment.webUiSimulatorScreenshotsDirectory.existsSync()) {
      environment.webUiSimulatorScreenshotsDirectory.createSync();
    }
    // Temporary directories are deleted in the clenaup phase of after `felt`
    // runs the tests.
    temporaryDirectories.add(environment.webUiSimulatorScreenshotsDirectory);
  }

  /// This scale factor is used to enlarge/shrink the screenshot region
  /// sent from the tests.
  /// For more details see [_scaleScreenshotRegion(region)].
  late final double _scaleFactor;

  /// Height of the part to crop from the top of the image.
  ///
  /// `xcrun simctl` command takes the screenshot of the entire simulator. We
  /// are cropping top bit from screenshot, otherwise due to the clock on top of
  /// the screen, the screenshot will differ between each run.
  /// Note that this gap can change per phone and per iOS version. For more
  /// details refer to `browser_lock.yaml` file.
  late final int _heightOfHeader;

  /// Height of the part to crop from the bottom of the image.
  ///
  /// This area is the footer navigation bar of the phone, it is not the area
  /// used by tests (which is inside the browser).
  late final int _heightOfFooter;

  /// Used as a suffix for the temporary file names used for screenshots.
  int _fileNameCounter = 0;

  /// Capture a screenshot of entire simulator.
  ///
  /// Example screenshot with dimensions: W x H.
  ///
  ///  <----------  W ------------->
  ///  _____________________________
  /// | Phone Top bar (clock etc.)  |   Ʌ
  /// |_____________________________|   |
  /// | Broswer search bar          |   |
  /// |_____________________________|   |
  /// | Web page content            |   |
  /// |                             |   |
  /// |                             |
  /// |                             |   H
  /// |                             |
  /// |                             |   |
  /// |                             |   |
  /// |                             |   |
  /// |                             |   |
  /// |_____________________________|   |
  /// | Phone footer bar            |   |
  /// |_____________________________|   V
  ///
  /// After taking the screenshot, the image is cropped as heigh as
  /// [_heightOfHeader] and [_heightOfFooter] from the top and bottom parts
  /// consecutively. Hence web content has the dimensions:
  ///
  /// W x (H - [_heightOfHeader] - [_heightOfFooter])
  ///
  /// [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.
  ///
  /// Uses simulator tool `xcrun simctl`'s 'screenshot' command.
  @override
  Future<Image> capture(math.Rectangle<num>? region) async {
    final String filename = 'screenshot$_fileNameCounter.png';
    _fileNameCounter++;

    await iosSimulator.takeScreenshot(
      filename, environment.webUiSimulatorScreenshotsDirectory,
    );

    final io.File file = io.File(path.join(
        environment.webUiSimulatorScreenshotsDirectory.path, filename));
    List<int> imageBytes;
    if (!file.existsSync()) {
      throw Exception('Failed to read the screenshot '
          'screenshot$_fileNameCounter.png.');
    }
    imageBytes = await file.readAsBytes();
    file.deleteSync();

    final Image screenshot = decodePng(imageBytes)!;
    // Create an image with no footer and header. The _heightOfHeader,
    // _heightOfFooter values are already in real coordinates therefore
    // they don't need to be scaled.
    final Image content = copyCrop(
      screenshot,
      0,
      _heightOfHeader,
      screenshot.width,
      screenshot.height - _heightOfFooter - _heightOfHeader,
    );

    if (region == null) {
      return content;
    } else {
      final math.Rectangle<num> scaledRegion = _scaleScreenshotRegion(region);
      return copyCrop(
        content,
        scaledRegion.left.toInt(),
        scaledRegion.top.toInt(),
        scaledRegion.width.toInt(),
        scaledRegion.height.toInt(),
      );
    }
  }

  /// Perform a linear transform on the screenshot region to convert its
  /// dimensions from linear coordinated to coordinated on the phone screen.
  /// This uniform/isotropic scaling is done using [_scaleFactor].
  math.Rectangle<num> _scaleScreenshotRegion(math.Rectangle<num> region) {
    return math.Rectangle<num>(
      region.left * _scaleFactor,
      region.top * _scaleFactor,
      region.width * _scaleFactor,
      region.height * _scaleFactor,
    );
  }
}
