package configui

import (
	"encoding/json"
	"errors"
	"log"
	"os"
	"os/exec"
	"runtime"
	"sync"
)

var UNIX_SHELL = "bash"
var WIN_SHELL = "cmd"

type File struct {
	Path   string `json:"path"`
	Alias  string `json:"name"`
	Action string `json:"action"`
	RO     bool   `json:"ro"`

	// used for parsing post data
	Data string `json:"data"`

	lock sync.RWMutex `json:"-"`
}

func (f *File) Read() ([]byte, error) {
	f.lock.RLock()
	defer f.lock.RUnlock()
	data, err := os.ReadFile(f.Path)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	return data, nil
}

func (f *File) Write(data []byte) error {
	if f.RO {
		return errors.New("this file has readonly set")
	}
	f.lock.Lock()
	defer f.lock.Unlock()
	info, err := os.Stat(f.Path)
	if err != nil {
		return err
	}
	return os.WriteFile(f.Path, data, info.Mode())
}

func (f *File) Do() (string, error) {
	if f.Action == "" {
		return "", nil
	}
	cmd := exec.Command(UNIX_SHELL, "-c", f.Action)
	if runtime.GOOS == "windows" {
		cmd = exec.Command(WIN_SHELL, "/c", f.Action)
	}
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", err
	}
	return string(out), nil
}

func ReadConfig(confstr string) ([]File, error) {
	conf := []File{}
	err := json.Unmarshal([]byte(confstr), &conf)
	if err != nil {
		return nil, err
	}
	for i := range conf {
		if conf[i].Alias == "" {
			conf[i].Alias = conf[i].Path
		}
	}
	return conf, nil
}

func GetFileMap(files []File) map[string]*File {
	fileMap := map[string]*File{}
	for i := range files {
		fileMap[files[i].Alias] = &files[i]
	}
	return fileMap
}
