
// createMemos provides a function to create Seekia memos
// Memos are specially formatted messages that are signed with a Seekia identity key
// They can be shared anywhere, and verified using the Seekia application

package createMemos

import "seekia/internal/allowedText"
import "seekia/internal/cryptography/blake3"
import "seekia/internal/cryptography/edwardsKeys"
import "seekia/internal/encoding"
import "seekia/internal/identity"

import "strings"
import "errors"

//Outputs:
//	-string: Memo
//	-error
func CreateMemo(identityPublicKey [32]byte, identityPrivateKey [64]byte, identityType string, decorativePrefix string, decorativeSuffix string, memoMessage string)(string, error){

	authorIdentityHash, err := identity.ConvertIdentityKeyToIdentityHash(identityPublicKey, identityType)
	if (err != nil) { return "", err }

	authorIdentityHashString, _, err := identity.EncodeIdentityHashBytesToString(authorIdentityHash)
	if (err != nil) { return "", err }

	textIsAllowed := allowedText.VerifyStringIsAllowed(memoMessage)
	if (textIsAllowed == false){
		return "", errors.New("CreateMemo called with unallowed text.")
	}

	if (len(memoMessage) > 50000){
		return "", errors.New("CreateMemo called with memoMessage that is too long")
	}

	identityPublicKeyHex := encoding.EncodeBytesToHexString(identityPublicKey[:])

	identityPublicKeyPieceA := identityPublicKeyHex[:32]
	identityPublicKeyPieceB := identityPublicKeyHex[32:]

	// We use this to build the memo body
	var memoBodyBuilder strings.Builder

	memoBodyBuilder.WriteString("|- Identity Key:\n")
	memoBodyBuilder.WriteString("|    " + identityPublicKeyPieceA + "\n")
	memoBodyBuilder.WriteString("|    " + identityPublicKeyPieceB + "\n")
	memoBodyBuilder.WriteString("|\n")
	memoBodyBuilder.WriteString("|- Author:\n")
	memoBodyBuilder.WriteString("|    " + authorIdentityHashString + "\n")
	memoBodyBuilder.WriteString("|\n")
	memoBodyBuilder.WriteString("|- Memo:\n")
	memoBodyBuilder.WriteString("|\n")

	memoMessageLinesList := strings.Split(memoMessage, "\n")

	for _, messageLine := range memoMessageLinesList{

		if (messageLine == ""){

			// There is no content on this line. It only contains a newline.

			memoLine := "|\n"

			memoBodyBuilder.WriteString(memoLine)	

		} else {

			memoLine := "|    " + messageLine + "\n"

			memoBodyBuilder.WriteString(memoLine)
		}
	}

	memoBodyBuilder.WriteString("|\n")

	// The memo body is the part of the memo we will sign with the author's identity key
	memoBody := memoBodyBuilder.String()

	memoBodyBytes := []byte(memoBody)

	memoBodyHash, err := blake3.Get32ByteBlake3Hash(memoBodyBytes)
	if (err != nil) { return "", err }

	signatureBytes := edwardsKeys.CreateSignature(identityPrivateKey, memoBodyHash)

	signatureString := encoding.EncodeBytesToBase64String(signatureBytes[:])

	signaturePiece1 := signatureString[:30]
	signaturePiece2 := signatureString[30:60]
	signaturePiece3 := signatureString[60:]

	// We use this to build the memo header
	var memoHeaderBuilder strings.Builder

	memoHeaderBuilder.WriteString("| " + decorativePrefix + " Seekia Memo " + decorativeSuffix + "\n")
	memoHeaderBuilder.WriteString("|\n")
	memoHeaderBuilder.WriteString("|- Signature:\n")
	memoHeaderBuilder.WriteString("|    " + signaturePiece1 + "\n")
	memoHeaderBuilder.WriteString("|    " + signaturePiece2 + "\n")
	memoHeaderBuilder.WriteString("|    " + signaturePiece3 + "\n")
	memoHeaderBuilder.WriteString("|\n")

	memoHeader := memoHeaderBuilder.String()

	memoFooter := "| " + decorativePrefix + " End Of Memo " + decorativeSuffix

	newMemo := memoHeader + memoBody + memoFooter

	return newMemo, nil
}

