import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/foundation.dart' as foundation;
import 'package:crypto/crypto.dart' as crypto;
import 'package:encrypt/encrypt.dart';

class Crypto {
  static String encrypt(String plainText, String keyText, String ivText) {
    final key = Key(base64Decode(keyText));
    final iv = IV(base64Decode(ivText));
    final cipher = Encrypter(AES(key, mode: AESMode.ctr, padding: null));
    return cipher.encrypt(plainText, iv: iv).base64;
  }

  static Uint8List encryptUint8(
    String plainText,
    String keyText,
    String ivText,
  ) {
    final key = Key(base64Decode(keyText));
    final iv = IV(base64Decode(ivText));
    final cipher = Encrypter(AES(key, mode: AESMode.ctr, padding: null));
    return cipher.encrypt(plainText, iv: iv).bytes;
  }

  static String encryptBytes(
    List<int> plainText,
    String keyText,
    String ivText,
  ) {
    final key = Key(base64Decode(keyText));
    final iv = IV(base64Decode(ivText));
    final cipher = Encrypter(AES(key, mode: AESMode.ctr, padding: null));
    return cipher.encryptBytes(plainText, iv: iv).base64;
  }

  static Uint8List encryptBytesUint8(
    List<int> plainText,
    String keyText,
    String ivText,
  ) {
    final key = Key(base64Decode(keyText));
    final iv = IV(base64Decode(ivText));
    final cipher = Encrypter(AES(key, mode: AESMode.ctr, padding: null));
    return cipher.encryptBytes(plainText, iv: iv).bytes;
  }

  static String decrypt(String cipherText, String keyText, String ivText) {
    final key = Key(base64Decode(keyText));
    final iv = IV(base64Decode(ivText));
    final cipher = Encrypter(AES(key, mode: AESMode.ctr, padding: null));
    final Encrypted data = Encrypted.fromBase64(cipherText);
    return cipher.decrypt(data, iv: iv);
  }

  static List<int> decryptBytes(
    String cipherText,
    String keyText,
    String ivText,
  ) {
    final key = Key(base64Decode(keyText));
    final iv = IV(base64Decode(ivText));
    final cipher = Encrypter(AES(key, mode: AESMode.ctr, padding: null));
    final Encrypted data = Encrypted.fromBase64(cipherText);
    return cipher.decryptBytes(data, iv: iv);
  }

  static List<int> decryptBytesUint8(
    Uint8List cipherText,
    String keyText,
    String ivText,
  ) {
    final key = Key(base64Decode(keyText));
    final iv = IV(base64Decode(ivText));
    final cipher = Encrypter(AES(key, mode: AESMode.ctr, padding: null));
    final Encrypted data = Encrypted(cipherText);
    return cipher.decryptBytes(data, iv: iv);
  }

  static String _md5(String data) {
    return crypto.md5.convert(utf8.encode(data)).toString();
  }

  static Future<String> md5(String data) {
    return foundation.compute(_md5, data);
  }

  static Future<String> _md5File(String filename) async {
    final input = File(filename);
    if (!input.existsSync()) {
      return '';
    }
    final digest = await crypto.md5.bind(input.openRead()).first;
    return digest.toString();
  }

  static Future<String> md5File(String filename) {
    return foundation.compute(_md5File, filename);
  }

  static Future<String> signature(String input, String secret) async {
    final hmacSha1 = crypto.Hmac(crypto.sha1, utf8.encode(secret));
    final digest = hmacSha1.convert(utf8.encode(input));
    return digest.toString();
  }
}
