
// enabledHosts provides functions to retrieve and refresh a list of all enabled hosts
// An enabled host is a host whose profile is not disabled

package enabledHosts

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

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

var enabledHostsListMutex sync.RWMutex

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

// This variable stores the network type that the enabledHostsList belongs to
var enabledHostsListNetworkType byte

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

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

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

	return nil
}


func GetNumberOfEnabledHosts(allowCache bool, networkType byte)(int, error){

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

	currentEnabledHostsList, err := GetEnabledHostsList(allowCache, networkType)
	if (err != nil){ return 0, err }

	numberOfHosts := len(currentEnabledHostsList)

	return numberOfHosts, nil
}

func CheckIfHostIsEnabled(allowCache bool, hostIdentityHash [16]byte, networkType byte)(bool, error){

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

	currentEnabledHostsList, err := GetEnabledHostsList(allowCache, networkType)
	if (err != nil){ return false, err }

	isEnabled := slices.Contains(currentEnabledHostsList, hostIdentityHash)

	return isEnabled, nil
}

//Outputs:
//	-[][16]byte: List of enabled host identity hashes
//	-error
func GetEnabledHostsList(allowCache bool, networkType byte)([][16]byte, error){

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

	if (allowCache == true){

		enabledHostsListMutex.RLock()

		if (enabledHostsList != nil && enabledHostsListNetworkType == networkType){

			// A cache list is generated which belongs to the specified networkType

			listCopy := slices.Clone(enabledHostsList)

			enabledHostsListMutex.RUnlock()
			
			return listCopy, nil
		}

		// We must generate a new enabled hosts cache list

		enabledHostsListMutex.RUnlock()
	}

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

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

	for _, identityHash := range hostIdentityHashesList{

		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
		}

		newEnabledHostsList = append(newEnabledHostsList, identityHash)
	}

	enabledHostsListMutex.Lock()

	enabledHostsList = newEnabledHostsList
	enabledHostsListNetworkType = networkType

	listCopy := slices.Clone(enabledHostsList)

	enabledHostsListMutex.Unlock()

	return listCopy, nil
}




