import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:Capsule/models/my_profile.dart';
import 'package:Capsule/utils/storage/get_file.dart';
import 'package:Capsule/utils/storage/write_file.dart';
import 'package:mime/mime.dart';
import 'package:pointycastle/pointycastle.dart';
import 'package:uuid/uuid.dart';

import '/models/conversations.dart';
import '/models/messages.dart';
import '/utils/encryption/aes_helper.dart';
import '/utils/encryption/crypto_utils.dart';
import '/utils/strings.dart';

class ImageMessage extends Message {
  File file;

  ImageMessage({
    id,
    symmetricKey,
    userSymmetricKey,
    senderId,
    senderUsername,
    associationKey,
    createdAt,
    failedToSend,
    required this.file,
  }) : super(
    id: id,
    symmetricKey: symmetricKey,
    userSymmetricKey: userSymmetricKey,
    senderId: senderId,
    senderUsername: senderUsername,
    associationKey: associationKey,
    createdAt: createdAt,
    failedToSend: failedToSend,
  );

  static Future<ImageMessage> fromJson(Map<String, dynamic> json, RSAPrivateKey privKey) async {
    var userSymmetricKey = CryptoUtils.rsaDecrypt(
      base64.decode(json['symmetric_key']),
      privKey,
    );

    var symmetricKey = AesHelper.aesDecrypt(
      userSymmetricKey,
      base64.decode(json['message_data']['symmetric_key']),
    );

    var senderId = AesHelper.aesDecrypt(
      base64.decode(symmetricKey),
      base64.decode(json['message_data']['sender_id']),
    );

    File file = await getFile(
      '$defaultServerUrl/files/${json['message_data']['attachment']['image_link']}',
      '${json['id']}',
      symmetricKey,
    );

    return ImageMessage(
      id: json['id'],
      symmetricKey: symmetricKey,
      userSymmetricKey: base64.encode(userSymmetricKey),
      senderId: senderId,
      senderUsername: 'Unknown',
      associationKey: json['association_key'],
      createdAt: json['created_at'],
      failedToSend: false,
      file: file,
    );
  }

  @override
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'symmetric_key': symmetricKey,
      'user_symmetric_key': userSymmetricKey,
      'file': file.path,
      'sender_id': senderId,
      'sender_username': senderUsername,
      'association_key': associationKey,
      'created_at': createdAt,
      'failed_to_send': failedToSend ? 1 : 0,
    };
  }

  Future<Map<String, dynamic>> payloadJson(Conversation conversation) async {
    final String messageDataId = (const Uuid()).v4();

    final symmetricKey = AesHelper.deriveKey(generateRandomString(32));

    final userSymmetricKey = AesHelper.deriveKey(generateRandomString(32));

    List<Map<String, String>> messages = await super.payloadJsonBase(
      symmetricKey,
      userSymmetricKey,
      conversation,
      id,
      messageDataId,
    );

    Map<String, dynamic> messageData = {
      'id': messageDataId,
      'sender_id': AesHelper.aesEncrypt(symmetricKey, Uint8List.fromList(senderId.codeUnits)),
      'symmetric_key': AesHelper.aesEncrypt(
        userSymmetricKey,
        Uint8List.fromList(base64.encode(symmetricKey).codeUnits),
      ),
      'attachment': {
        'data': AesHelper.aesEncrypt(base64.encode(symmetricKey), Uint8List.fromList(file.readAsBytesSync())),
        'mimetype': lookupMimeType(file.path),
        'extension': getExtension(file.path),
      }
    };

    return <String, dynamic>{
      'message_data': messageData,
      'message': messages,
    };
  }

  @override
  String getContent() {
    return 'Image';
  }

  @override
  String toString() {
    return '''


      id: $id
      file: ${file.path},
      senderId: $senderId
      senderUsername: $senderUsername
      associationKey: $associationKey
      createdAt: $createdAt
      ''';
  }
}
