package settings

import (
	"cwtch.im/cwtch/event"
	"cwtch.im/cwtch/model/constants"
	"cwtch.im/cwtch/storage/v1"
	"encoding/json"
	"git.openprivacy.ca/openprivacy/log"
	"os"
	path "path/filepath"
	"runtime"
)

const (
	CwtchStarted         = event.Type("CwtchStarted")
	CwtchStartError      = event.Type("CwtchStartError")
	UpdateGlobalSettings = event.Type("UpdateGlobalSettings")
)

const GlobalSettingsFilename = "ui.globals"
const saltFile = "SALT"

type NotificationPolicy string

const (
	NotificationPolicyMute       = NotificationPolicy("NotificationPolicy.Mute")
	NotificationPolicyOptIn      = NotificationPolicy("NotificationPolicy.OptIn")
	NotificationPolicyDefaultAll = NotificationPolicy("NotificationPolicy.DefaultAll")
)

type GlobalSettingsFile struct {
	v1.FileStore
}

type GlobalSettings struct {
	Locale                  string
	Theme                   string
	ThemeMode               string
	ThemeImages             bool
	PreviousPid             int64
	ExperimentsEnabled      bool
	Experiments             map[string]bool
	BlockUnknownConnections bool
	NotificationPolicy      NotificationPolicy
	NotificationContent     string
	StreamerMode            bool
	StateRootPane           int
	FirstTime               bool
	UIColumnModePortrait    string
	UIColumnModeLandscape   string
	DownloadPath            string
	AllowAdvancedTorConfig  bool
	CustomTorrc             string
	UseCustomTorrc          bool
	UseExternalTor          bool
	CustomSocksPort         int
	CustomControlPort       int
	UseTorCache             bool
	TorCacheDir             string
	BlodeuweddPath          string
	FontScaling             float64
	DefaultSaveHistory      bool
}

var DefaultGlobalSettings = GlobalSettings{
	Locale:                  "en",
	Theme:                   "cwtch",
	ThemeMode:               "dark",
	ThemeImages:             false,
	PreviousPid:             -1,
	ExperimentsEnabled:      false,
	Experiments:             map[string]bool{constants.MessageFormattingExperiment: true},
	StateRootPane:           0,
	FirstTime:               true,
	BlockUnknownConnections: false,
	StreamerMode:            false,
	UIColumnModePortrait:    "DualpaneMode.Single",
	UIColumnModeLandscape:   "DualpaneMode.CopyPortrait",
	NotificationPolicy:      "NotificationPolicy.Mute",
	NotificationContent:     "NotificationContent.SimpleEvent",
	DownloadPath:            "",
	AllowAdvancedTorConfig:  false,
	CustomTorrc:             "",
	UseCustomTorrc:          false,
	CustomSocksPort:         -1,
	CustomControlPort:       -1,
	UseTorCache:             false,
	TorCacheDir:             "",
	BlodeuweddPath:          "",
	FontScaling:             1.0, // use the system pixel scaling default
	DefaultSaveHistory:      false,
}

func InitGlobalSettingsFile(directory string, password string) (*GlobalSettingsFile, error) {
	var key [32]byte
	salt, err := os.ReadFile(path.Join(directory, saltFile))
	if err != nil {
		log.Infof("Could not find salt file: %v (creating a new settings file)", err)
		var newSalt [128]byte
		key, newSalt, err = v1.CreateKeySalt(password)
		if err != nil {
			log.Errorf("Could not initialize salt: %v", err)
			return nil, err
		}
		err := os.MkdirAll(directory, 0700)
		if err != nil {
			return nil, err
		}
		err = os.WriteFile(path.Join(directory, saltFile), newSalt[:], 0600)
		if err != nil {
			log.Errorf("Could not write salt file: %v", err)
			return nil, err
		}
	} else {
		key = v1.CreateKey(password, salt)
	}

	gsFile := v1.NewFileStore(directory, GlobalSettingsFilename, key)
	log.Infof("initialized global settings file: %v", gsFile)
	globalSettingsFile := GlobalSettingsFile{
		gsFile,
	}
	return &globalSettingsFile, nil
}

func GenerateDefaultSettings() GlobalSettings {
	settings := DefaultGlobalSettings
	if runtime.GOOS == "android" || runtime.GOOS == "ios" {
		settings.UIColumnModePortrait = "DualpaneMode.Single"
	} else {
		settings.UIColumnModePortrait = "DualpaneMode.Dual1to2"
	}
	return settings
}

func (globalSettingsFile *GlobalSettingsFile) ReadGlobalSettings() GlobalSettings {
	settings := GenerateDefaultSettings()

	if globalSettingsFile == nil {
		log.Errorf("Global Settings File was not Initialized Properly")
		return settings
	}

	settingsBytes, err := globalSettingsFile.Read()
	if err != nil {
		log.Infof("Could not read global ui settings: %v (assuming this is a first time app deployment...)", err)
		return settings //firstTime = true
	}

	// note: by giving json.Unmarshal settings we are providing it defacto defaults
	// from DefaultGlobalSettings
	err = json.Unmarshal(settingsBytes, &settings)
	if err != nil {
		log.Errorf("Could not parse global ui settings: %v\n", err)
		// TODO if settings is corrupted, we probably want to alert the UI.
		return settings //firstTime = true
	}

	log.Debugf("Settings: %#v", settings)
	return settings
}

func (globalSettingsFile *GlobalSettingsFile) WriteGlobalSettings(globalSettings GlobalSettings) {
	bytes, _ := json.Marshal(globalSettings)
	// override first time setting
	globalSettings.FirstTime = true
	err := globalSettingsFile.Write(bytes)
	if err != nil {
		log.Errorf("Could not write global ui settings: %v\n", err)
	}
}
