
// myIgnoredUsers provides functions to manage a mate user's ignored users
// Ignored users can be toggled to be hidden or shown in the user's matches and chat conversations
// This toggle can be useful if the user has run out of matches and wants to give users they were initially not interested in a second chance

package myIgnoredUsers

import "seekia/internal/encoding"
import "seekia/internal/helpers"
import "seekia/internal/identity"
import "seekia/internal/myDatastores/myMapList"

import "sync"
import "errors"
import "time"

// We lock this mutex whenever we add a new ignored user
// We do this to prevent adding duplicates
var addingIgnoredUsersMutex sync.Mutex

var myIgnoredUsersMapListDatastore *myMapList.MyMapList

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

	addingIgnoredUsersMutex.Lock()
	defer addingIgnoredUsersMutex.Unlock()

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

	myIgnoredUsersMapListDatastore = newMyIgnoredUsersMapListDatastore

	return nil
}

func IgnoreUser(userIdentityHash [16]byte, reasonProvided bool, reason string)error{

	userIdentityHashString, userIdentityType, err := identity.EncodeIdentityHashBytesToString(userIdentityHash)
	if (err != nil) {
		userIdentityHashHex := encoding.EncodeBytesToHexString(userIdentityHash[:])
		return errors.New("IgnoreUser called with invalid identity hash: " + userIdentityHashHex)
	}
	if (userIdentityType != "Mate"){
		return errors.New("IgnoreUser called with non-mate identity hash: " + userIdentityType)
	}

	addingIgnoredUsersMutex.Lock()
	defer addingIgnoredUsersMutex.Unlock()

	userIsIgnored, _, _, _, err := CheckIfUserIsIgnored(userIdentityHash)
	if (err != nil){ return err }
	if (userIsIgnored == true){
		// The GUI should prevent this.
		return errors.New("IgnoreUser called when user is already ignored.")
	}

	currentTimeInt := time.Now().Unix()
	currentTimeString := helpers.ConvertInt64ToString(currentTimeInt)

	newMapItem := map[string]string{
		"IdentityHash": userIdentityHashString,
		"IgnoredTime": currentTimeString,
	}

	if (reasonProvided == true){
		newMapItem["Reason"] = reason
	}

	err = myIgnoredUsersMapListDatastore.AddMapListItem(newMapItem)
	if (err != nil) { return err }

	return nil
}

func UnignoreUser(userIdentityHash [16]byte)error{
	
	userIdentityHashString, userIdentityType, err := identity.EncodeIdentityHashBytesToString(userIdentityHash)
	if (err != nil) {
		userIdentityHashHex := encoding.EncodeBytesToHexString(userIdentityHash[:])
		return errors.New("UnignoreUser called with invalid identity hash: " + userIdentityHashHex)
	}
	if (userIdentityType != "Mate"){
		return errors.New("UnignoreUser called with non-mate identity hash: " + userIdentityType)
	}

	mapToDelete := map[string]string{
		"IdentityHash": userIdentityHashString,
	}

	err = myIgnoredUsersMapListDatastore.DeleteMapListItems(mapToDelete)
	if (err != nil) { return err }

	return nil
}

func GetMyIgnoredUsersMapList()([]map[string]string, error){

	myIgnoredUsersMapList, err := myIgnoredUsersMapListDatastore.GetMapList()
	if (err != nil) { return nil, err }

	return myIgnoredUsersMapList, nil
}

//Outputs:
//	-bool: User is Ignored
//	-int64: Unix time of ignoring
//	-bool: Reason provided
//	-string: Reason for ignoring
//	-error
func CheckIfUserIsIgnored(userIdentityHash [16]byte)(bool, int64, bool, string, error){

	userIdentityHashString, userIdentityType, err := identity.EncodeIdentityHashBytesToString(userIdentityHash)
	if (err != nil) {
		userIdentityHashHex := encoding.EncodeBytesToHexString(userIdentityHash[:])
		return false, 0, false, "", errors.New("CheckIfUserIsIgnored called with invalid identity hash: " + userIdentityHashHex)
	}
	if (userIdentityType != "Mate"){
		return false, 0, false, "", errors.New("CheckIfUserIsIgnored called with non-mate identity hash: " + userIdentityType)
	}

	lookupMap := map[string]string{
		"IdentityHash": userIdentityHashString,
	}

	anyItemsFound, ignoredUsersMapList, err := myIgnoredUsersMapListDatastore.GetMapListItems(lookupMap)
	if (err != nil) { return false, 0, false, "", err }
	if (anyItemsFound == false){
		return false, 0, false, "", nil
	}

	if (len(ignoredUsersMapList) != 1){
		return false, 0, false, "", errors.New("Ignored users mapList contains more than 1 entry for an identity hash")
	}

	ignoredUserMapItem := ignoredUsersMapList[0]

	ignoredTimeString, exists := ignoredUserMapItem["IgnoredTime"]
	if (exists == false) {
		return false, 0, false, "", errors.New("Ignored users mapList contains item missing IgnoredTime")
	}

	ignoredTimeInt64, err := helpers.ConvertStringToInt64(ignoredTimeString)
	if (err != nil) {
		return false, 0, false, "", errors.New("Ignored users mapList contains item with invalid IgnoredTime: " + ignoredTimeString)
	}

	reason, reasonExists := ignoredUserMapItem["Reason"]
	if (reasonExists == false){
		return true, ignoredTimeInt64, false, "", nil
	}

	return true, ignoredTimeInt64, true, reason, nil
}


