
// enabledModerators provides functions to retrieve and refresh a list of all enabled moderators
// An enabled moderator is a moderator whose profile is not disabled

package enabledModerators

import "seekia/internal/badgerDatabase"
import "seekia/internal/helpers"
import "seekia/internal/profiles/profileStorage"
import "seekia/internal/profiles/readProfiles"

import "slices"
import "sync"
import "errors"

var enabledModeratorsListMutex sync.RWMutex

// This list stores all enabled moderators
// It will not necessarily be up to date
var enabledModeratorsList [][16]byte

// This variable stores the network type that the enabledModerators list belongs to
var enabledModeratorsListNetworkType byte

// This function must be called upon application startup, and then again on a regular automatic interval
// It must also be called whenever the application network type is changed
func UpdateEnabledModeratorsList(networkType byte)error{

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

	enabledModeratorsListMutex.Lock()
	enabledModeratorsList = nil
	enabledModeratorsListNetworkType = 0
	enabledModeratorsListMutex.Unlock()

	_, err := GetEnabledModeratorsList(false, networkType)
	if (err != nil) { return err }

	return nil
}

//Outputs:
//	-int: Number of enabled moderators
//	-error
func GetNumberOfEnabledModerators(allowCache bool, networkType byte)(int, error){

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

	currentEnabledModeratorsList, err := GetEnabledModeratorsList(allowCache, networkType)
	if (err != nil) { return 0, err }

	numberOfModerators := len(currentEnabledModeratorsList)

	return numberOfModerators, nil
}

//Outputs:
//	-bool: Moderator is enabled
//	-error
func CheckIfModeratorIsEnabled(allowCache bool, moderatorIdentityHash [16]byte, networkType byte)(bool, error){

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

	currentEnabledModeratorsList, err := GetEnabledModeratorsList(allowCache, networkType)
	if (err != nil) { return false, err }

	isEnabled := slices.Contains(currentEnabledModeratorsList, moderatorIdentityHash)

	return isEnabled, nil
}


// This function returns enabled moderators list for current app network type
//Outputs:
//	-[][16]byte: List of enabled moderator identity hashes
//	-error
func GetEnabledModeratorsList(allowCache bool, networkType byte)([][16]byte, error){

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

	if (allowCache == true){

		enabledModeratorsListMutex.RLock()

		if (enabledModeratorsList != nil && enabledModeratorsListNetworkType == networkType){

			// enabledModeratorsList is generated and belongs to the requested networkType

			listCopy := slices.Clone(enabledModeratorsList)

			enabledModeratorsListMutex.RUnlock()

			return listCopy, nil
		}

		enabledModeratorsListMutex.RUnlock()
	}

	// We must generate a new enabled moderators cache list

	moderatorIdentityHashesList, err := badgerDatabase.GetAllProfileIdentityHashes("Moderator")
	if (err != nil) { return nil, err }

	newEnabledModeratorsList := make([][16]byte, 0)

	for _, identityHash := range moderatorIdentityHashesList{

		profileExists, _, _, _, _, newestRawProfileMap, err := profileStorage.GetNewestUserProfile(identityHash, networkType)
		if (err != nil) { return nil, err }
		if (profileExists == false){
			// Profile does not exist anymore.
			// Missing entries from Identity Profiles list will be removed automatically by backgroundJobs
			continue
		}

		profileIsDisabled, _, err := readProfiles.GetFormattedProfileAttributeFromRawProfileMap(newestRawProfileMap, "Disabled")
		if (err != nil) { return nil, err }
		if (profileIsDisabled == true){
			continue
		}

		newEnabledModeratorsList = append(newEnabledModeratorsList, identityHash)
	}

	enabledModeratorsListMutex.Lock()

	enabledModeratorsList = newEnabledModeratorsList
	enabledModeratorsListNetworkType = networkType

	listCopy := slices.Clone(enabledModeratorsList)

	enabledModeratorsListMutex.Unlock()

	return listCopy, nil
}


