
// mySecretInboxes provides functions to manage a user's secret inboxes
// User sends these inboxes out in messages to users
// They must check them for messages until they expire

package mySecretInboxes

//TODO: Prune expired inboxes we have checked sufficiently

import "seekia/internal/encoding"
import "seekia/internal/helpers"
import "seekia/internal/identity"
import "seekia/internal/messaging/inbox"
import "seekia/internal/messaging/secretInboxEpoch"
import "seekia/internal/myBlockedUsers"
import "seekia/internal/myDatastores/myMapList"

import "bytes"
import "sync"
import "errors"

// This will be locked whenever we update the map list
var updatingMySecretInboxesMapListMutex sync.Mutex

var mySecretInboxesMapListDatastore *myMapList.MyMapList

// This function must be called whenever an app user signs in
func InitializeMySecretInboxesDatastore()error{

	updatingMySecretInboxesMapListMutex.Lock()
	defer updatingMySecretInboxesMapListMutex.Unlock()

	newMySecretInboxesMapListDatastore, err := myMapList.CreateNewMapList("MySecretInboxes")
	if (err != nil) { return err }

	mySecretInboxesMapListDatastore = newMySecretInboxesMapListDatastore

	return nil
}


// This function will omit inboxes that we no longer need to download messages for
// This would be because they have been sufficiently checked and old enough that no new messages are being received
func GetAllMyActiveSecretInboxes(myIdentityHash [16]byte, networkType byte)([][10]byte, error){

	isValid, err := identity.VerifyIdentityHash(myIdentityHash, false, "")
	if (err != nil) { return nil, err }
	if (isValid == false){
		myIdentityHashHex := encoding.EncodeBytesToHexString(myIdentityHash[:])
		return nil, errors.New("GetAllMyActiveSecretInboxes called with invalid myIdentityHash: " + myIdentityHashHex)
	}

	isValid = helpers.VerifyNetworkType(networkType)
	if (isValid == false){
		networkTypeString := helpers.ConvertByteToString(networkType)
		return nil, errors.New("GetAllMyActiveSecretInboxes called with invalid networkType: " + networkTypeString)
	}

	mySecretInboxesList, err := GetAllMySecretInboxes(myIdentityHash, networkType)
	if (err != nil){ return nil, err }

	//TODO: We need code that keeps track of how many times we have checked a particular inbox after it has expired
	// Then we will omit those inboxes

	return mySecretInboxesList, nil
}

// This function will not return inboxes for users whom the user has blocked
func GetAllMySecretInboxes(myIdentityHash [16]byte, networkType byte)([][10]byte, error){

	isValid, err := identity.VerifyIdentityHash(myIdentityHash, false, "")
	if (err != nil) { return nil, err }
	if (isValid == false){
		myIdentityHashHex := encoding.EncodeBytesToHexString(myIdentityHash[:])
		return nil, errors.New("GetAllMySecretInboxes called with invalid myIdentityHash: " + myIdentityHashHex)
	}

	isValid = helpers.VerifyNetworkType(networkType)
	if (isValid == false){
		networkTypeString := helpers.ConvertByteToString(networkType)
		return nil, errors.New("GetAllMySecretInboxes called with invalid networkType: " + networkTypeString)
	}

	mySecretInboxesMapList, err := mySecretInboxesMapListDatastore.GetMapList()
	if (err != nil) { return nil, err }

	allMySecretInboxesList := make([][10]byte, 0)

	for _, inboxMap := range mySecretInboxesMapList{

		conversationMyIdentityHashString, exists := inboxMap["MyIdentityHash"]
		if (exists == false){
			return nil, errors.New("mySecretInboxesMapList is malformed: Item missing MyIdentityHash.")
		}

		conversationMyIdentityHash, _, err := identity.ReadIdentityHashString(conversationMyIdentityHashString)
		if (err != nil){
			return nil, errors.New("mySecretInboxesMapList is malformed: Item contains invalid MyIdentityHash: " + conversationMyIdentityHashString)
		}

		if (conversationMyIdentityHash != myIdentityHash){
			continue
		}

		recipientIdentityHashString, exists := inboxMap["TheirIdentityHash"]
		if (exists == false){
			return nil, errors.New("mySecretInboxesMapList is malformed: Item missing TheirIdentityHash")
		}

		recipientIdentityHash, _, err := identity.ReadIdentityHashString(recipientIdentityHashString)
		if (err != nil){
			return nil, errors.New("mySecretInboxesMapList is malformed: Item contains invalid TheirIdentityHash: " + recipientIdentityHashString)
		}

		recipientIsBlocked, _, _, _, err := myBlockedUsers.CheckIfUserIsBlocked(recipientIdentityHash)
		if (err != nil){ return nil, err }
		if (recipientIsBlocked == true){
			continue
		}

		inboxNetworkTypeString, exists := inboxMap["NetworkType"]
		if (exists == false){
			return nil, errors.New("mySecretInboxesMapList is malformed: Item missing NetworkType.")
		}

		inboxNetworkType, err := helpers.ConvertNetworkTypeStringToByte(inboxNetworkTypeString)
		if (err != nil){
			return nil, errors.New("mySecretInboxesMapList is malformed: Item contains invalid NetworkType: " + inboxNetworkTypeString)
		}

		if (inboxNetworkType != networkType){
			continue
		}

		secretInboxSeedHex, exists := inboxMap["SecretInboxSeed"]
		if (exists == false){
			return nil, errors.New("mySecretInboxesMapList is malformed: Item missing SecretInboxSeed.")
		}

		secretInboxSeed, err := encoding.DecodeHexStringToBytes(secretInboxSeedHex)
		if (err != nil){
			return nil, errors.New("mySecretInboxesMapList is malformed: Contains invalid secretInboxSeed: Not Hex.")
		}

		if (len(secretInboxSeed) != 22){
			return nil, errors.New("mySecretInboxesMapList is malformed: Contains invalid secretInboxSeed: Invalid length.")
		}

		secretInboxSeedArray := [22]byte(secretInboxSeed)

		currentSecretInbox, _, err := inbox.GetSecretInboxAndSealerKeyFromSecretInboxSeed(secretInboxSeedArray)
		if (err != nil){ return nil, err }

		allMySecretInboxesList = append(allMySecretInboxesList, currentSecretInbox)
	}

	return allMySecretInboxesList, nil
}

//Outputs:
//	-bool: My secret inbox found
//	-[16]byte: Conversation my identity hash
//	-[16]byte: Conversation recipient identity hash
//	-byte: Secret inbox network type
//	-[32]byte: Secret inbox sealer key
//	-int64: Secret inbox start time
//	-int64: Secret inbox expiration time
//	-error
func GetMySecretInboxInfo(secretInbox [10]byte)(bool, [16]byte, [16]byte, byte, [32]byte, int64, int64, error){

	mySecretInboxesMapList, err := mySecretInboxesMapListDatastore.GetMapList()
	if (err != nil) { return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, err }

	for _, inboxMap := range mySecretInboxesMapList{

		secretInboxSeedHex, exists := inboxMap["SecretInboxSeed"]
		if (exists == false){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxesMapList is malformed: Inbox map missing SecretInboxSeed")
		}

		secretInboxSeed, err := encoding.DecodeHexStringToBytes(secretInboxSeedHex)
		if (err != nil){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxes map list malformed: Contains invalid secretInboxSeed: Not Hex.")
		}

		if (len(secretInboxSeed) != 22){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxes map list malformed: Contains invalid secretInboxSeed: Invalid length.")
		}

		secretInboxSeedArray := [22]byte(secretInboxSeed)

		currentSecretInbox, currentSecretInboxSealerKey, err := inbox.GetSecretInboxAndSealerKeyFromSecretInboxSeed(secretInboxSeedArray)
		if (err != nil){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxes map list malformed: Contains invalid secretInboxSeed.")
		}

		if (currentSecretInbox != secretInbox){
			continue
		}

		conversationMyIdentityHashString, exists := inboxMap["MyIdentityHash"]
		if (exists == false){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxesMapList is malformed: Inbox map missing MyIdentityHash")
		}

		conversationMyIdentityHash, _, err := identity.ReadIdentityHashString(conversationMyIdentityHashString)
		if (err != nil){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxesMapList is malformed: Inbox map contains invalid MyIdentityHash: " + conversationMyIdentityHashString)
		}
		
		conversationTheirIdentityHashString, exists := inboxMap["TheirIdentityHash"]
		if (exists == false){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxesMapList is malformed: Inbox map missing TheirIdentityHash")
		}

		conversationTheirIdentityHash, _, err := identity.ReadIdentityHashString(conversationTheirIdentityHashString)
		if (err != nil){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxesMapList is malformed: Inbox map contains invalid TheirIdentityHash: " + conversationTheirIdentityHashString)
		}

		inboxNetworkTypeString, exists := inboxMap["NetworkType"]
		if (exists == false){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxesMapList is malformed: Inbox map missing NetworkType")
		}

		inboxNetworkType, err := helpers.ConvertNetworkTypeStringToByte(inboxNetworkTypeString)
		if (err != nil){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxesMapList is malformed: Inbox map contains invalid NetworkType: " + inboxNetworkTypeString)
		}

		inboxStartTimeString, exists := inboxMap["InboxStartTime"]
		if (exists == false){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxesMapList is malformed: Inbox map missing InboxStartTime")
		}

		inboxStartTimeInt64, err := helpers.ConvertStringToInt64(inboxStartTimeString)
		if (err != nil) {
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("Malformed mySecretInboxesMapList: Invalid secret inbox start time: " + inboxStartTimeString)
		}

		inboxEndTimeString, exists := inboxMap["InboxEndTime"]
		if (exists == false){
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("MySecretInboxesMapList is malformed: Inbox map missing InboxEndTime")
		}

		inboxEndTimeInt64, err := helpers.ConvertStringToInt64(inboxEndTimeString)
		if (err != nil) {
			return false, [16]byte{}, [16]byte{}, 0, [32]byte{}, 0, 0, errors.New("Malformed mySecretInboxesMapList: Invalid secret inbox end time: " + inboxEndTimeString)
		}

		return true, conversationMyIdentityHash, conversationTheirIdentityHash, inboxNetworkType, currentSecretInboxSealerKey, inboxStartTimeInt64, inboxEndTimeInt64, nil
	}

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


//Outputs:
//	-bool: Parameters exist
//	-bool: My current epoch secret inbox seed exists
//	-[22]byte: My current epoch secret inbox seed
//	-bool: My next epoch secret inbox seed exists
//	-[22]byte: My next epoch secret inbox seed
//	-error
func GetMySecretInboxSeedsForMessage(myIdentityHash [16]byte, recipientIdentityHash [16]byte, networkType byte, messageCreationTimeUnix int64)(bool, bool, [22]byte, bool, [22]byte, error){

	isValid, err := identity.VerifyIdentityHash(myIdentityHash, false, "")
	if (err != nil){ return false, false, [22]byte{}, false, [22]byte{}, err }
	if (isValid == false){
		myIdentityHashHex := encoding.EncodeBytesToHexString(myIdentityHash[:])
		return false, false, [22]byte{}, false, [22]byte{}, errors.New("GetMySecretInboxSeedsForMessage called with invalid myIdentityHash: " + myIdentityHashHex)
	}

	isValid = helpers.VerifyNetworkType(networkType)
	if (isValid == false){
		networkTypeString := helpers.ConvertByteToString(networkType)
		return false, false, [22]byte{}, false, [22]byte{}, errors.New("GetMySecretInboxSeedsForMessage called with invalid networkType: " + networkTypeString)
	}

	parametersExist, currentEpochStartTime, currentEpochEndTime, nextEpochStartTime, nextEpochEndTime, err := secretInboxEpoch.GetSecretInboxEpochStartAndEndTimes(networkType, messageCreationTimeUnix)
	if (err != nil) { return false, false, [22]byte{}, false, [22]byte{}, err }	
	if (parametersExist == false){
		return false, false, [22]byte{}, false, [22]byte{}, nil
	}

	myIdentityHashString, _, err := identity.EncodeIdentityHashBytesToString(myIdentityHash)
	if (err != nil){
		myIdentityHashHex := encoding.EncodeBytesToHexString(myIdentityHash[:])
		return false, false, [22]byte{}, false, [22]byte{}, errors.New("VerifyIdentityHash failed to verify identity hash: " + myIdentityHashHex)
	}

	recipientIdentityHashString, _, err := identity.EncodeIdentityHashBytesToString(recipientIdentityHash)
	if (err != nil){
		recipientIdentityHashHex := encoding.EncodeBytesToHexString(recipientIdentityHash[:])
		return false, false, [22]byte{}, false, [22]byte{}, errors.New("GetMySecretInboxSeedsForMessage called with invalid recipient identity hash: " + recipientIdentityHashHex)
	}

	// We retrieve all secret inboxes for this conversation, and find an inbox that exists for the entire desired epoch duration

	networkTypeString := helpers.ConvertByteToString(networkType)

	lookupMap := map[string]string{
		"MyIdentityHash": myIdentityHashString,
		"TheirIdentityHash": recipientIdentityHashString,
		"NetworkType": networkTypeString,
	}

	anyItemsFound, foundItemsMapList, err := mySecretInboxesMapListDatastore.GetMapListItems(lookupMap)
	if (err != nil) { return false, false, [22]byte{}, false, [22]byte{}, err }
	if (anyItemsFound == false){
		return true, false, [22]byte{}, false, [22]byte{}, nil
	}	

	//Outputs:
	//	-bool: Inbox found
	//	-[22]byte: Secret inbox seed
	//	-error
	getSecretInboxSeedForEpoch := func(epochStartTime int64, epochEndTime int64)(bool, [22]byte, error){

		for _, inboxMap := range foundItemsMapList{

			inboxStartTimeString, exists := inboxMap["InboxStartTime"]
			if (exists == false){
				return false, [22]byte{}, errors.New("MySecretInboxesMapList is malformed: Item missing InboxStartTime")
			}
	
			inboxStartTimeInt64, err := helpers.ConvertStringToInt64(inboxStartTimeString)
			if (err != nil) {
				return false, [22]byte{}, errors.New("MySecretInboxesMapList is malformed: Invalid secret inbox start time: " + inboxStartTimeString)
			}

			inboxEndTimeString, exists := inboxMap["InboxEndTime"]
			if (exists == false){
				return false, [22]byte{}, errors.New("MySecretInboxesMapList is malformed: Item missing InboxEndTime")
			}

			inboxEndTimeInt64, err := helpers.ConvertStringToInt64(inboxEndTimeString)
			if (err != nil) {
				return false, [22]byte{}, errors.New("MySecretInboxesMapList is malformed: Invalid secret inbox end time: " + inboxEndTimeString)
			}

			if (inboxStartTimeInt64 > epochStartTime || inboxEndTimeInt64 < epochEndTime){
				continue
			}

			secretInboxSeedHex, exists := inboxMap["SecretInboxSeed"]
			if (exists == false){
				return false, [22]byte{}, errors.New("MySecretInboxesMapList is malformed: Item missing SecretInboxSeed")
			}
			secretInboxSeed, err := encoding.DecodeHexStringToBytes(secretInboxSeedHex)
			if (err != nil){
				return false, [22]byte{}, errors.New("MySecretInboxesMapList is malformed: Invalid secret inbox seed: " + secretInboxSeedHex)
			}

			if (len(secretInboxSeed) != 22){
				return false, [22]byte{}, errors.New("MySecretInboxesMapList is malformed: Invalid secret inbox seed: " + secretInboxSeedHex)
			}

			secretInboxSeedArray := [22]byte(secretInboxSeed)

			return true, secretInboxSeedArray, nil
		}

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

	foundCurrentEpochInboxSeed, currentEpochInboxSeed, err := getSecretInboxSeedForEpoch(currentEpochStartTime, currentEpochEndTime)
	if (err != nil) { return false, false, [22]byte{}, false, [22]byte{}, err }

	foundNextEpochInboxSeed, nextEpochInboxSeed, err := getSecretInboxSeedForEpoch(nextEpochStartTime, nextEpochEndTime)
	if (err != nil) { return false, false, [22]byte{}, false, [22]byte{}, err }
	
	return true, foundCurrentEpochInboxSeed, currentEpochInboxSeed, foundNextEpochInboxSeed, nextEpochInboxSeed, nil
}


//Outputs:
//	-bool: Parameters exist
//	-error
func AddMySecretInboxSeeds(myIdentityHash [16]byte, theirIdentityHash [16]byte, networkType byte, messageCreationTime int64, currentSecretInboxSeed [22]byte, nextSecretInboxSeed [22]byte)(bool, error){

	isValid, err := identity.VerifyIdentityHash(myIdentityHash, false, "")
	if (err != nil) { return false, err }
	if (isValid == false){
		myIdentityHashHex := encoding.EncodeBytesToHexString(myIdentityHash[:])
		return false, errors.New("AddMySecretInboxSeeds called with invalid myIdentityHash: " + myIdentityHashHex)
	}
	isValid, err = identity.VerifyIdentityHash(theirIdentityHash, false, "")
	if (err != nil) { return false, err }
	if (isValid == false){
		theirIdentityHashHex := encoding.EncodeBytesToHexString(theirIdentityHash[:])
		return false, errors.New("AddMySecretInboxSeeds called with invalid theirIdentityHash: " + theirIdentityHashHex)
	}

	isValid = helpers.VerifyNetworkType(networkType)
	if (isValid == false){
		networkTypeString := helpers.ConvertByteToString(networkType)
		return false, errors.New("AddMySecretInboxSeeds called with invalid networkType: " + networkTypeString)
	}

	updatingMySecretInboxesMapListMutex.Lock()
	defer updatingMySecretInboxesMapListMutex.Unlock()

	parametersExist, currentSecretInboxStartTime, currentSecretInboxEndTime, nextSecretInboxStartTime, nextSecretInboxEndTime, err := secretInboxEpoch.GetSecretInboxEpochStartAndEndTimes(networkType, messageCreationTime)
	if (err != nil) { return false, err }
	if (parametersExist == false){
		return false, nil
	}

	mySecretInboxesMapList, err := mySecretInboxesMapListDatastore.GetMapList()
	if (err != nil) { return false, err }

	addSecretInboxSeedToMapList := func(secretInboxSeed [22]byte, inboxStartTime int64, inboxEndTime int64)error{

		// We see if an entry already exists for this inbox

		for _, inboxMap := range mySecretInboxesMapList{

			currentSecretInboxSeedString, exists := inboxMap["SecretInboxSeed"]
			if (exists == false){
				return errors.New("mySecretInboxesMapListDatastore is malformed: Item missing SecretInboxSeed")
			}

			currentSecretInboxSeedBytes, err := encoding.DecodeHexStringToBytes(currentSecretInboxSeedString)
			if (err != nil){
				return errors.New("mySecretInboxesMapListDatastore is malformed: Item contains invalid SecretInboxSeed: Not Hex.")
			}

			if (len(currentSecretInboxSeedBytes) != 22){
				return errors.New("mySecretInboxesMapListDatastore is malformed: Item contains invalid SecretInboxSeed: Invalid length.")
			}

			areEqual := bytes.Equal(currentSecretInboxSeedBytes, secretInboxSeed[:])
			if (areEqual == false){
				continue
			}

			conversationMyIdentityHashString, exists := inboxMap["MyIdentityHash"]
			if (exists == false){
				return errors.New("Malformed mySecretInboxesMapListDatastore: Item missing MyIdentityHash")
			}

			conversationMyIdentityHash, _, err := identity.ReadIdentityHashString(conversationMyIdentityHashString)
			if (err != nil){
				return errors.New("Malformed mySecretInboxesMapListDatastore: Item contains invalid MyIdentityHash: " + conversationMyIdentityHashString)
			}

			if (conversationMyIdentityHash != myIdentityHash){
				// This should never happen. Secret inbox seeds are generated randomly.
				return errors.New("Trying to add a secret inbox seed which already exists for a different identity.")
			}

			conversationTheirIdentityHashString, exists := inboxMap["TheirIdentityHash"]
			if (exists == false) {
				return errors.New("Malformed mySecretInboxesMapListDatastore: Item missing TheirIdentityHash")
			}

			conversationTheirIdentityHash, _, err := identity.ReadIdentityHashString(conversationTheirIdentityHashString)
			if (err != nil){
				return errors.New("Malformed mySecretInboxesMapListDatastore: Item contains invalid TheirIdentityHash: " + conversationTheirIdentityHashString)
			}

			if (conversationTheirIdentityHash != theirIdentityHash){
				// This should never happen. Secret inbox seeds are generated randomly.
				return errors.New("Trying to add a secret inbox seed which already exists for a different recipient identity.")
			}

			inboxNetworkTypeString, exists := inboxMap["NetworkType"]
			if (exists == false){
				return errors.New("Malformed mySecretInboxesMapListDatastore: Item missing NetworkType")
			}

			inboxNetworkType, err := helpers.ConvertNetworkTypeStringToByte(inboxNetworkTypeString)
			if (err != nil){
				return errors.New("Malformed mySecretInboxesMapListDatastore: Item contains invalid NetworkType: " + inboxNetworkTypeString)
			}
			if (inboxNetworkType != networkType){
				// This should never happen. Secret inbox seeds are generated randomly.
				return errors.New("Trying to add a secret inbox seed that already exists with a different networkType.")
			}

			existingInboxStartTimeString, exists := inboxMap["InboxStartTime"]
			if (exists == false){
				return errors.New("mySecretInboxesMapListDatastore is malformed: Item missing InboxStartTime")
			}

			existingInboxStartTime, err := helpers.ConvertStringToInt64(existingInboxStartTimeString)
			if (err != nil) {
				return errors.New("Malformed mySecretInboxesMapList: Invalid secret inbox start time: " + existingInboxStartTimeString)
			}

			existingInboxEndTimeString, exists := inboxMap["InboxEndTime"]
			if (exists == false){
				return errors.New("mySecretInboxesMapListDatastore is malformed: Item missing InboxEndTime")
			}

			existingInboxEndTime, err := helpers.ConvertStringToInt64(existingInboxEndTimeString)
			if (err != nil) {
				return errors.New("Malformed mySecretInboxesMapList: Invalid secret inbox end time: " + existingInboxEndTimeString)
			}

			// We see if the existing inbox start/end times are earlier/later than what we have recorded
			// This would only happen if secret inbox epoch duration was changed

			if (inboxStartTime >= existingInboxStartTime && inboxEndTime <= existingInboxEndTime){
				// Existing inbox range bounds are valid.
				// Nothing to change
				return nil
			}

			// Inbox range must be expanded
			// Secret inbox epoch duration must have changed (or sender is malicious)

			newInboxStartTime := min(existingInboxStartTime, inboxStartTime)

			newInboxEndTime := max(existingInboxEndTime, inboxEndTime)

			newSecretInboxStartTimeString := helpers.ConvertInt64ToString(newInboxStartTime)
			newSecretInboxEndTimeString := helpers.ConvertInt64ToString(newInboxEndTime)

			inboxMap["InboxStartTime"] = newSecretInboxStartTimeString
			inboxMap["InboxEndTime"] = newSecretInboxEndTimeString

			return nil
		}

		// This is only reached if inbox map does not exist
		// We create and append a new inbox map

		myIdentityHashString, _, err := identity.EncodeIdentityHashBytesToString(myIdentityHash)
		if (err != nil) {
			myIdentityHashHex := encoding.EncodeBytesToHexString(myIdentityHash[:])
			return errors.New("VerifyIdentityHash failed to verify myIdentityHash: " + myIdentityHashHex)
		}

		theirIdentityHashString, _, err := identity.EncodeIdentityHashBytesToString(theirIdentityHash)
		if (err != nil) {
			theirIdentityHashHex := encoding.EncodeBytesToHexString(theirIdentityHash[:])
			return errors.New("VerifyIdentityHash failed to verify theirIdentityHash: " + theirIdentityHashHex)
		}

		secretInboxSeedHex := encoding.EncodeBytesToHexString(secretInboxSeed[:])
		networkTypeString := helpers.ConvertByteToString(networkType)

		secretInboxStartTimeString := helpers.ConvertInt64ToString(currentSecretInboxStartTime)
		secretInboxEndTimeString := helpers.ConvertInt64ToString(currentSecretInboxEndTime)

		newInboxMap := map[string]string{
			"MyIdentityHash": myIdentityHashString,
			"TheirIdentityHash": theirIdentityHashString,
			"SecretInboxSeed": secretInboxSeedHex,
			"NetworkType": networkTypeString,
			"InboxStartTime": secretInboxStartTimeString,
			"InboxEndTime": secretInboxEndTimeString,
		}

		mySecretInboxesMapList = append(mySecretInboxesMapList, newInboxMap)

		return nil
	}

	err = addSecretInboxSeedToMapList(currentSecretInboxSeed, currentSecretInboxStartTime, currentSecretInboxEndTime)
	if (err != nil) { return false, err }

	err = addSecretInboxSeedToMapList(nextSecretInboxSeed, nextSecretInboxStartTime, nextSecretInboxEndTime)
	if (err != nil) { return false, err }

	err = mySecretInboxesMapListDatastore.OverwriteMapList(mySecretInboxesMapList)
	if (err != nil) { return false, err }

	return true, nil
}



