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

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 TextMessage extends Message {
  String text;

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

  factory TextMessage.fromJson(Map<String, dynamic> json, RSAPrivateKey privKey) {
    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']),
    );

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

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

  @override
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'symmetric_key': symmetricKey,
      'user_symmetric_key': userSymmetricKey,
      'data': text,
      '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, String> messageData = {
      'id': messageDataId,
      'data': AesHelper.aesEncrypt(symmetricKey, Uint8List.fromList(text.codeUnits)),
      'sender_id': AesHelper.aesEncrypt(symmetricKey, Uint8List.fromList(senderId.codeUnits)),
      'symmetric_key': AesHelper.aesEncrypt(
        userSymmetricKey,
        Uint8List.fromList(base64.encode(symmetricKey).codeUnits),
      ),
    };

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

  @override
  String getContent() {
    return text;
  }

  @override
  String toString() {
    return '''


      id: $id
      data: $text,
      senderId: $senderId
      senderUsername: $senderUsername
      associationKey: $associationKey
      createdAt: $createdAt
      ''';
  }
}
