// 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:io';
import 'dart:typed_data';
import 'dart:ui';

import 'package:path/path.dart' as path;
import 'package:skia_gold_client/skia_gold_client.dart';

import 'impeller_enabled.dart';

const String _kSkiaGoldWorkDirectoryKey = 'kSkiaGoldWorkDirectory';

/// A helper for doing image comparison (golden) tests.
///
/// Contains utilities for comparing two images in memory that are expected to
/// be identical, or for adding images to Skia gold for comparison.
class ImageComparer {
  ImageComparer._({
    required SkiaGoldClient client,
  }) : _client = client;

  // Avoid talking to Skia gold for the force-multithreading variants.
  static bool get _useSkiaGold =>
      !Platform.executableArguments.contains('--force-multithreading');

  /// Creates an image comparer and authorizes.
  static Future<ImageComparer> create({
    bool verbose = false,
  }) async {
    const String workDirectoryPath =
        String.fromEnvironment(_kSkiaGoldWorkDirectoryKey);
    if (workDirectoryPath.isEmpty) {
      throw UnsupportedError(
          'Using ImageComparer requries defining kSkiaGoldWorkDirectoryKey.');
    }

    final Directory workDirectory = Directory(
      impellerEnabled ? '${workDirectoryPath}_iplr' : workDirectoryPath,
    )..createSync();
    final Map<String, String> dimensions = <String, String>{
      'impeller_enabled': impellerEnabled.toString(),
    };
    final SkiaGoldClient client = SkiaGoldClient.isAvailable() && _useSkiaGold
        ? SkiaGoldClient(workDirectory,
            dimensions: dimensions, verbose: verbose)
        : _FakeSkiaGoldClient(workDirectory, dimensions, verbose: verbose);

    await client.auth();
    return ImageComparer._(client: client);
  }

  final SkiaGoldClient _client;

  /// Adds an [Image] to Skia Gold for comparison.
  ///
  /// The [fileName] must be unique.
  Future<void> addGoldenImage(Image image, String fileName) async {
    final ByteData data =
        (await image.toByteData(format: ImageByteFormat.png))!;

    final File file = File(path.join(_client.workDirectory.path, fileName))
      ..writeAsBytesSync(data.buffer.asUint8List());
    await _client.addImg(
      fileName,
      file,
      screenshotSize: image.width * image.height,
    ).catchError((dynamic error) {
      print('Skia gold comparison failed: $error');
      throw Exception('Failed comparison: $fileName');
    });
  }

  Future<bool> fuzzyCompareImages(Image golden, Image testImage) async {
    if (golden.width != testImage.width || golden.height != testImage.height) {
      return false;
    }
    int getPixel(ByteData data, int x, int y) =>
        data.getUint32((x + y * golden.width) * 4);
    final ByteData goldenData = (await golden.toByteData())!;
    final ByteData testImageData = (await testImage.toByteData())!;
    for (int y = 0; y < golden.height; y++) {
      for (int x = 0; x < golden.width; x++) {
        if (getPixel(goldenData, x, y) != getPixel(testImageData, x, y)) {
          return false;
        }
      }
    }
    return true;
  }
}

// TODO(dnfield): add local comparison against baseline,
// https://github.com/flutter/flutter/issues/136831
class _FakeSkiaGoldClient implements SkiaGoldClient {
  _FakeSkiaGoldClient(
    this.workDirectory,
    this.dimensions, {
    this.verbose = false,
  });

  @override
  final Directory workDirectory;

  @override
  final Map<String, String> dimensions;

  @override
  final bool verbose;

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

  @override
  Future<void> addImg(
    String testName,
    File goldenFile, {
    double differentPixelsRate = 0.01,
    int pixelColorDelta = 0,
    required int screenshotSize,
  }) async {}

  @override
  dynamic noSuchMethod(Invocation invocation) {
    throw UnimplementedError(invocation.memberName.toString().split('"')[1]);
  }
}
