package config

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"

	"github.com/go-yaml/yaml"
)

const (
	defaultPort     int = 8080
	defaultHostname     = "localhost"
)

var (
	defaultBuild = "NODATE"
)

type ServiceConfig struct {
	PortNum int `json:"port" yaml:"port"`
}

type Config struct {
	Service  ServiceConfig `json:"service"   yaml:"service"`
	Hostname string        `json:"hostname"  yaml:"hostname"`
	Debug    bool          `json:"debug"     yaml:"debug"`
	Build    string        `json:"build"     yaml:"build"`
	LogPath  string        `json:"logfile"   yaml:"logfile"`
	RunPath  string        `json:"runfile"   yaml:"runfile"`
	DataPath string        `json:"datadir"   yaml:"datadir"`
        SharePath string       `json:"sharedir"  yaml:"sharedir"`
	Daemon   bool          `json:"daemon"    yaml:"daemon"`
}

func NewConfig() *Config {
	conf := &Config{
		Service: ServiceConfig{
			PortNum: defaultPort,
		},
		Debug:    false,
		Hostname: defaultHostname,
		Build:    defaultBuild,
                SharePath: sharedirPath,
		DataPath: datadirPath,
	}

	exeName := filepath.Base(os.Args[0])
	conf.LogPath = filepath.Join(logdirPath, fmt.Sprintf("%s.log", exeName))
	conf.RunPath = filepath.Join(rundirPath, fmt.Sprintf("%s.pid", exeName))
	return conf
}

func (conf *Config) ReadFile() error {
	var err error
	exeName := filepath.Base(os.Args[0])
	configPath := filepath.Join(confdirPath, fmt.Sprintf("%s.yaml", exeName))
	confBytes, err := os.ReadFile(configPath)
	if err != nil {
		return err
	}
	err = yaml.Unmarshal(confBytes, conf)
	if err != nil {
		return err
	}
	return err
}

func (conf *Config) ReadEnv() error {
	var err error
	return err
}

func (conf *Config) ReadOpts() error {
	var err error

	exeName := filepath.Base(os.Args[0])

	flag.IntVar(&conf.Service.PortNum, "port", conf.Service.PortNum, "listen port")
	flag.BoolVar(&conf.Daemon, "daemon", conf.Daemon, "run as daemon")
	flag.BoolVar(&conf.Debug, "debug", conf.Debug, "on debug mode")

	help := func() {
		fmt.Println("")
		fmt.Printf("Usage: %s [option]\n", exeName)
		fmt.Println("")
		fmt.Println("Options:")
		flag.PrintDefaults()
		fmt.Println("")
	}
	flag.Usage = help
	flag.Parse()

	return err
}

func (conf *Config) Yaml() (string, error) {
	var err error
	var res string
	yamlBytes, err := yaml.Marshal(conf)
	if err != nil {
		return res, err
	}
	res = string(yamlBytes)
	return res, err
}
