
// globalSettings provides functions to manage global settings, which are the same for all users.

package globalSettings

import goFilepath "path/filepath"
import "os"
import "encoding/json"
import "errors"
import "sync"

func InitializeGlobalSettingsDatastore()error{

	localFileDirectory, err := os.UserConfigDir()
	if (err != nil) { return err }
	
	globalSettingsFolderpath := goFilepath.Join(localFileDirectory, "SeekiaData", "GlobalSettings")

	// We create the GlobalSettings folder

	file, err := os.Open(globalSettingsFolderpath)
	if (err != nil){

		isNotExistErr := os.IsNotExist(err)
		if (isNotExistErr == false) {
			return err
		}

		// Folder does not exist
		err = os.Mkdir(globalSettingsFolderpath, os.ModePerm)
		if (err != nil) { return err }
	}
	file.Close()

	getCurrentSettingsMap := func()(map[string]string, error){

		globalSettingsFilepath := goFilepath.Join(globalSettingsFolderpath, "GlobalSettings.json")

		fileBytes, err := os.ReadFile(globalSettingsFilepath)
		if (err != nil){

			isNotExistError := os.IsNotExist(err)
			if (isNotExistError == false){
				return nil, err
			}

			emptyMap := make(map[string]string)
			return emptyMap, nil
		}

		currentMap := make(map[string]string)

		err = json.Unmarshal(fileBytes, &currentMap)
		if (err != nil) {
			return nil, errors.New("Stored globalSettings map is corrupted: " + err.Error()) 
		}

		return currentMap, nil
	}
	
	currentGlobalSettingsMap, err := getCurrentSettingsMap()
	if (err != nil) { return err }

	settingsMap = currentGlobalSettingsMap

	return nil
}

// This will be locked whenever we are writing the map/local file
var updatingSettingsMutex sync.Mutex

var settingsMapMutex sync.RWMutex

var settingsMap map[string]string

//Outputs:
//	-bool: Setting exists
//	-string: Setting value
//	-error
func GetSetting(settingName string)(bool, string, error){

	if (settingsMap == nil){
		return false, "", errors.New("GetSetting called when global settings map is not initialized.")
	}

	settingsMapMutex.RLock()
	settingString, exists := settingsMap[settingName]
	settingsMapMutex.RUnlock()

	if (exists == false){
		return false, "", nil
	}
	return true, settingString, nil
}

func SetSetting(settingName string, content string) error{

	if (settingName == ""){
		return errors.New("globalSettings SetSetting called with empty settingName.")
	}
	if (content == ""){
		return errors.New("globalSettings SetSetting called with empty content.")
	}

	updatingSettingsMutex.Lock()
	defer updatingSettingsMutex.Unlock()

	settingsMapMutex.Lock()
	settingsMap[settingName] = content
	settingsMapMutex.Unlock()

	overwriteSettingsFile()
	
	return nil
}

func DeleteSetting(settingName string) error {

	if (settingName == ""){
		return errors.New("globalSettings DeleteSetting called with empty settingName.")
	}

	updatingSettingsMutex.Lock()
	defer updatingSettingsMutex.Unlock()

	settingsMapMutex.Lock()
	delete(settingsMap, settingName)
	settingsMapMutex.Unlock()

	err := overwriteSettingsFile()
	if (err != nil) { return err }	
	
	return nil
}

func overwriteSettingsFile()error{

	jsonFileContents, err := json.MarshalIndent(settingsMap, "", "\t")
	if (err != nil) { return err }

	fileContentsString := string(jsonFileContents)

	localFileDirectory, err := os.UserConfigDir() 
	if (err != nil) { return err }
	
	globalSettingsFilepath := goFilepath.Join(localFileDirectory, "SeekiaData", "GlobalSettings", "GlobalSettings.json")
	
	newFile, err := os.Create(globalSettingsFilepath)
	if (err != nil) { return err }

	_, err = newFile.WriteString(fileContentsString)
	if (err != nil) {
		newFile.Close()
		return err
	}
	newFile.Close()

	return nil
}



