
// chatMessageStorage provides functions for storing and retrieving raw chat messages.
// This package stores encrypted messages. The myChatMessages package is where decrypted messages are stored.

package chatMessageStorage

import "seekia/internal/badgerDatabase"
import "seekia/internal/messaging/myInbox"
import "seekia/internal/messaging/readMessages"
import "seekia/internal/moderation/reportStorage"
import "seekia/internal/moderation/reviewStorage"
import "seekia/internal/mySettings"

import "errors"


func GetNumberOfStoredMessages()(int64, error){

	numberOfMessages, err := badgerDatabase.GetNumberOfChatMessages()
	if (err != nil) { return 0, err }
	
	return numberOfMessages, nil
}

// Returns all downloaded raw message hashes
// These are different from myChatMessages, which are decrypted
func GetAllDownloadedMessageHashes()([][26]byte, error){

	messageHashes, err := badgerDatabase.GetAllChatMessageHashes()
	if (err != nil) { return nil, err }

	return messageHashes, nil
}

//Outputs:
//	-bool: Message is well formed
//	-error
func AddMessage(inputMessage []byte)(bool, error){

	ableToRead, messageHash, _, messageNetworkType, recipientInbox, _, _, _, _, _, _, err := readMessages.ReadChatMessagePublicDataAndHash(true, inputMessage)
	if (err != nil) { return false, err }
	if (ableToRead == false){
		// Message is malformed, do nothing.
		// This means that the other host is malicious
		return false, nil
	}

	exists, _, err := badgerDatabase.GetChatMessage(messageHash)
	if (err != nil) { return false, err }
	if (exists == true){
		// Message already exists in the database.
		return true, nil
	}

	err = badgerDatabase.AddChatInboxMessage(recipientInbox, messageHash)
	if (err != nil) { return false, err }

	err = badgerDatabase.AddChatMessage(messageHash, inputMessage)
	if (err != nil) { return false, err }

	err = mySettings.SetSetting("ViewedContentNeedsRefreshYesNo", "Yes")
	if (err != nil) { return false, err }

	inboxIsMine, inboxIdentityType, err := myInbox.CheckIfInboxIsMine(recipientInbox, messageNetworkType)
	if (err != nil) { return false, err }
	if (inboxIsMine == true){

		err = mySettings.SetSetting(inboxIdentityType + "ChatConversationsNeedRefreshYesNo", "Yes")
		if (err != nil) { return false, err }
	}
	
	return true, nil
}


// This function will attempt to decrypt a message and return the communication
// We attempt to find a cipher key for the message from any downloaded reviews/reports
//Outputs:
//	-bool: Message exists (in storage)
//	-bool: Cipher key found
//	-bool: Message is decryptable
//	-[32]byte: Message Cipher Key
//	-[16]byte: Message sender
//	-string: Message communication
//	-error
func GetDecryptedMessageForModeration(messageHash [26]byte)(bool, bool, bool, [32]byte, [16]byte, string, error){

	messageExists, messageBytes, err := badgerDatabase.GetChatMessage(messageHash)
	if (err != nil) { return false, false, false, [32]byte{}, [16]byte{}, "", err }
	if (messageExists == false){

		return false, false, false, [32]byte{}, [16]byte{}, "", nil
	}

	ableToRead, _, messageNetworkType, _, _, _, _, messageCipherKeyHash, _, _, err := readMessages.ReadChatMessagePublicData(false, messageBytes)
	if (err != nil) { return false, false, false, [32]byte{}, [16]byte{}, "", err }
	if (ableToRead == false){
		return false, false, false, [32]byte{}, [16]byte{}, "", errors.New("Database corrupt: Contains invalid message.")
	}

	getMessageCipherKey := func()(bool, [32]byte, error){

		cipherKeyFound, cipherKey, err := reportStorage.GetMessageCipherKeyFromAnyReport(messageHash, messageNetworkType, messageCipherKeyHash)
		if (err != nil) { return false, [32]byte{}, err }
		if (cipherKeyFound == true){
			return true, cipherKey, nil
		}

		cipherKeyFound, cipherKey, err = reviewStorage.GetMessageCipherKeyFromAnyReview(messageHash, messageNetworkType, messageCipherKeyHash)
		if (err != nil) { return false, [32]byte{}, err }
		if (cipherKeyFound == true){
			return true, cipherKey, nil
		}

		return false, [32]byte{}, nil
	}

	cipherKeyFound, messageCipherKey, err := getMessageCipherKey()
	if (err != nil) { return false, false, false, [32]byte{}, [16]byte{}, "", err }
	if (cipherKeyFound == false){
		return true, false, false, [32]byte{}, [16]byte{}, "", nil
	}

	ableToRead, messageHash_Received, _, messageNetworkType_Received, senderIdentityHash, messageCommunication, err := readMessages.ReadChatMessageWithCipherKey(messageBytes, messageCipherKey)
	if (err != nil) { return false, false, false, [32]byte{}, [16]byte{}, "", err }
	if (ableToRead == false){
		// Message is malformed
		// It must have been created by a malicious author.
		return true, true, false, [32]byte{}, [16]byte{}, "", nil
	}
	if (messageHash_Received != messageHash){
		return false, false, false, [32]byte{}, [16]byte{}, "", errors.New("ReadChatMessageWithCipherKey returning different messageHash than ReadChatMessagePublicData")
	}
	if (messageNetworkType_Received != messageNetworkType){
		return false, false, false, [32]byte{}, [16]byte{}, "", errors.New("Database corrupt: Contains message with different message hash than entry key.")
	}

	return true, true, true, messageCipherKey, senderIdentityHash, messageCommunication, nil
}



