
// getParameters provides functions to retrieve network parameters
// Parameters are downloaded by all Seekia clients, and contain variables that are necessary to use Seekia
// Parameters are authored and updated by the admin(s)

package getParameters

//TODO: Complete package
//	There are many more parameters to be added, some of which are outlined in the documentation
//	We must also figure out the best gold weight to use, and the correct types to store the values (math.Big?)

//TODO: Add client-coded limits for some of the parameters
// If the limits are exceeded, we know the admin key(s) have been compromised, and the client should either wait for new permissions
//	to be downloaded, or they will be instructed to download a new client.

import "seekia/internal/encoding"
import "seekia/internal/helpers"
import "seekia/internal/identity"
import "seekia/internal/unixTime"

import "slices"
import "errors"


//Outputs:
//	-bool: Parameters exist
//	-error
func CheckIfMessageCostParametersExist(networkType byte)(bool, error){

	//TODO: Will check to make sure message cost parameters exist

	return true, nil
}

// This will check to see if all necessary parameters for chatting exist
func CheckIfChatParametersExist(networkType byte)(bool, error){

	parametersExist, err := CheckIfMessageCostParametersExist(networkType)
	if (err != nil) { return false, err }
	if (parametersExist == false){
		return false, nil
	}

	//TODO
	// secret inbox epoch parameters and more

	return true, nil
}


//Outputs:
//	-bool: Relevant parameters exists
//	-[][16]byte: List of Supermoderator identity hashes (Ranked from highest to lowest)
//	-error
func GetSupermoderatorIdentityHashesList(networkType byte)(bool, [][16]byte, error){
	
	//TODO:
	// Will read from network parameter list of supermoderators

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

	return true, emptyList, nil
}


//Outputs:
//	-bool: Parameters found
//	-bool: Moderator is supermoderator
//	-error
func CheckIfModeratorIsSupermoderator(inputIdentityHash [16]byte, networkType byte)(bool, bool, error){

	isValid, err := identity.VerifyIdentityHash(inputIdentityHash, true, "Moderator")
	if (err != nil){ return false, false, err }
	if (isValid == false){
		inputIdentityHashHex := encoding.EncodeBytesToHexString(inputIdentityHash[:])
		return false, false, errors.New("CheckIfModeratorIsSupermoderator called with invalid identity hash: " + inputIdentityHashHex)
	}

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


	parametersFound, supermoderatorIdentityHashesList, err := GetSupermoderatorIdentityHashesList(networkType)
	if (err != nil) { return false, false, err }
	if (parametersFound == false){
		return false, false, nil
	}

	isSupermoderator := slices.Contains(supermoderatorIdentityHashesList, inputIdentityHash)

	return true, isSupermoderator, nil
}


func CheckIfSecretInboxEpochParametersExist(networkType byte)(bool, error){

	//TODO

	return true, nil
}

//Outputs:
//	-bool: Parameters exist
//	-int64: Epoch duration in seconds
//	-error
func GetSecretInboxEpochDuration(networkType byte, timeMessageSent int64)(bool, int64, error){
	
	//TODO
	// Output: Amount of time after a constant start time that represents the start of a new epoch on a repeating period
	// Example: If start time is Unix time 10, and duration is 100, epoch starts/ends at 110, 210, 310, 410....
	// The parameters need to contain the historical durations for at least 2 weeks (the longest time a message can be active on the network)

	return true, 604800, nil
	
}

// This is the amount of time a mate profile should be hosted before expiring from the network
// This applies to Mate profiles.
// If a user identity balance expires, then the profile can expire before this time has passed
// Moderator profiles never expire
//Outputs:
//	-bool: Parameters exist
//	-int64: Network expiration duration in seconds (returns a fallback value if parameters are missing)
//	-error
func GetMateProfileMaximumExistenceDuration(networkType byte)(bool, int64, error){

	//TODO

	duration := unixTime.GetMonthUnix() * 3

	return true, duration, nil
}

//Outputs:
//	-bool: Parameters exist
//	-int64: Number of seconds until host profile is dropped from network (returns a fallback value if parameters are missing)
//	-error
func GetHostProfileMaximumExistenceDuration(networkType byte)(bool, int64, error){

	//TODO:
	// Output: Returns the length of time that a host profile is active
	// Hosts must constantly broadcast new profiles to stay on the network

	return true, 10000, nil
}


//Outputs:
//	-bool: Parameters exist
//	-float64: Identity network cost per day / grams gold (atomic units) //TODO: change from gram to milligram?
//	-error
func GetIdentityBalanceGoldCostPerDay(networkType byte, identityType string, creationTime int64)(bool, float64, error){

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

	if (identityType != "Mate" && identityType != "Host"){
		// Moderator identities are funded through identity scores, not identity balances
		return false, 0, errors.New("GetIdentityBalanceGoldCostPerDay called with invalid identityType: " + identityType)
	}

	//TODO
	// Output: Cost per day to fund an identity balance on the network
	// Example: If output is 1 gram, then funding an identity for a month costs 30 grams

	return true, 100, nil
}

//Outputs:
//	-bool: Parameters exist
//	-float64: Cost in grams of gold to fund 1KB message for 1 day
//	-error
func GetMessageKilobyteGoldCostPerDay(networkType byte, creationTime int64)(bool, float64, error){

	//TODO
	// This represents the amount of gold it costs to fund a message on the network
	// Output: Cost to fund a 1 kilobyte message for 1 day

	// Example: If cost is 100, and person wants to fund 10KB message for 2 weeks, they must spend 100*10*14 grams of gold to fund

	return true, 100, nil
}

//Outputs:
//	-bool: Parameters exist
//	-float64: Cost in grams of gold to fund a report
//	-error
func GetFundReportCostInGold(networkType byte, creationTime int64)(bool, float64, error){

	//TODO
	// This represents the amount of gold it costs to fund a report on the network

	return true, 150, nil
}

//Outputs:
//	-bool: Parameters exist
//	-float64: Grams of gold cost to fund a mate profile
//	-error
func GetFundMateProfileCostInGold(networkType byte, creationTime int64)(bool, float64, error){

	//TODO
	// This will return the cost in gold to fund a mate profile
	// Each mate profile must be funded
	// This is to prevent moderators from being spammed with new profiles to review
	// The mate identity must also be funded

	return true, 100, nil
}


//Outputs:
//	-bool: Parameters exist
//	-int64: Amount of cryptocurrency atomic units to buy 1 kilogram of gold at inputTime
//	-error
func GetCryptoAtomicUnitsPerKilogramOfGold(networkType byte, cryptocurrency string, inputTime int64)(bool, int64, error){

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

	if (cryptocurrency != "Ethereum" && cryptocurrency != "Cardano"){
		return false, 0, errors.New("GetCryptoUnitsPerKilogramOfGold called with invalid cryptocurrency: " + cryptocurrency)
	}

	//TODO

	return true, 10, nil
}

//Outputs:
//	-bool: Parameters exist
//	-float64: Amount of currency units worth 1 kilogram of gold
//	-error
func GetAnyCurrencyUnitsPerKilogramOfGold(networkType byte, currencyCode string)(bool, float64, error){
	
	//TODO
	// Outputs the exchange rate of a currency to kilograms of gold

	return true, 100, nil
}




