import 'dart:io';
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:moxxmpp/moxxmpp.dart';
import 'package:moxxyv2/i18n/strings.g.dart';
import 'package:native_imaging/native_imaging.dart' as native;

Future<String?> _generateBlurhashThumbnailImpl(String path) async {
  await native.init();

  final bytes = await File(path).readAsBytes();

  native.Image image;
  int width;
  int height;
  try {
    final dartCodec = await instantiateImageCodec(bytes);
    final dartFrame = await dartCodec.getNextFrame();
    final rgbaData = await dartFrame.image.toByteData();
    if (rgbaData == null) return null;

    width = dartFrame.image.width;
    height = dartFrame.image.height;

    dartFrame.image.dispose();
    dartCodec.dispose();

    image = native.Image.fromRGBA(
      width,
      height,
      Uint8List.view(
        rgbaData.buffer,
        rgbaData.offsetInBytes,
        rgbaData.lengthInBytes,
      ),
    );
  } catch (_) {
    // TODO(PapaTutuWawa): Log error
    return null;
  }

  // Scale the image down as recommended by
  // https://github.com/woltapp/blurhash#how-fast-is-encoding-decoding
  final scaled = image.resample(
    20,
    (height * (width / height)).toInt(),
    native.Transform.bilinear,
  );

  // Calculate the blurhash
  final blurhash = scaled.toBlurhash(3, 3);

  // Free resources
  image.free();
  scaled.free();
  return blurhash;
}

/// Generate a blurhash thumbnail using native_imaging.
Future<String?> generateBlurhashThumbnail(String path) async {
  return compute(_generateBlurhashThumbnailImpl, path);
}

/// Turn a XmppError into its corresponding translated string.
String xmppErrorToTranslatableString(XmppError error) {
  if (error is StartTLSFailedError) {
    return t.errors.login.startTlsFailed;
  } else if (error is SaslFailedError) {
    return t.errors.login.saslFailed;
  } else if (error is NoConnectionError) {
    return t.errors.login.noConnection;
  }
  
  return t.errors.login.unspecified;
}

String getStickerHashKeyType(Map<String, String> hashes) {
  if (hashes.containsKey('blake2b-512')) {
    return 'blake2b-512';
  } else if (hashes.containsKey('blake2b-512')) {
    return 'blake2b-256';
  } else if (hashes.containsKey('sha3-512')) {
    return 'sha3-512';
  } else if (hashes.containsKey('sha3-256')) {
    return 'sha3-256';
  } else if (hashes.containsKey('sha3-256')) {
    return 'sha-512';
  } else if (hashes.containsKey('sha-256')) {
    return 'sha-256';
  }

  assert(false, 'No valid hash found');
  return '';

}

String getStickerHashKey(Map<String, String> hashes) {
  final key = getStickerHashKeyType(hashes);
  return '$key:${hashes[key]}';
}
