package setting

import (
	"errors"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/go-ini/ini"
	"github.com/jacobsa/go-serial/serial"
)

var (
	AppSetting       = &App{}
	ServerSetting    = &Server{}
	CommSetting      = &serial.OpenOptions{}
	SnowIds          *IdWorker
	DatabaseSetting  = &Database{}
	SQlserverSetting = &SQlserver{}
	YynserverSetting = &Yyn{}
	cfg              *ini.File
	CurrentPath      string
)

type App struct {
	JwtSecret string
	PageSize  int
	PrefixUrl string

	RuntimeRootPath string

	FileSavePath  string
	FileMaxSize   int      // 普通文件上传的限制大小,单位byte, 最大单位1GB
	FileAllowType []string // 允许上传的文件后缀名

	ImageSavePath  string
	ImageMaxSize   int
	ImageAllowExts []string

	ThumbnailSavePath  string
	ThumbnailMaxWidth  int
	ThumbnailMaxHeight int

	ExportSavePath string
	QrCodeSavePath string
	FontSavePath   string

	LogSavePath string
	LogSaveName string
	LogFileExt  string
	TimeFormat  string
}

type Server struct {
	RunMode          string
	HttpPort         int
	ReadTimeout      time.Duration
	WriteTimeout     time.Duration
	NoAuth           int
	Mdns_servicename string
	Mdns_serviceport int
	HttpsPort        int
	Https            int
	CrtPath          string
	KeyPath          string
	ServerName       string
	DisplayName      string
	Description      string
	GRFD             string
	GRFDURL          string
}

type Database struct {
	Type          string
	User          string
	Password      string
	Host          string
	Name          string
	ShowXormlog   bool
	ShowGetSqllog bool
	CacheApiSql   bool
	TablePrefix   string
}

type SQlserver struct {
	Host     string
	User     string
	Password string
	Name     string
}

type Yyn struct {
	FarmId       string
	ProductKey   string
	DeviceName   string
	DeviceSecret string
	HeartBeat    string
}

func Setup(dir string) {
	var err error
	if strings.Trim(dir, " ") == "" {
		CurrentPath, err = GetCurrentPath()
	} else {
		CurrentPath = dir
	}
	cfg, err = ini.Load(CurrentPath + "conf/app.ini")
	if err != nil {
		log.Fatalf("setting.Setup, fail to parse 'conf/app.ini': %v", err)
	}

	SnowIds, err = NewIdWorker(1)
	if err != nil {
		log.Fatalf("setting.Setup, fail to create SnowIds: %v", err)
	}
	DatabaseSetting.ShowXormlog = false
	DatabaseSetting.ShowGetSqllog = false
	DatabaseSetting.CacheApiSql = false
	mapTo("app", AppSetting)
	mapTo("server", ServerSetting)
	mapTo("database", DatabaseSetting)
	mapTo("comm", CommSetting)
	mapTo("sqlserver", SQlserverSetting)

	mapTo("yyn", YynserverSetting)
	AppSetting.ImageMaxSize = AppSetting.ImageMaxSize * 1024 * 1024
	ServerSetting.ReadTimeout = ServerSetting.ReadTimeout * time.Second
	ServerSetting.WriteTimeout = ServerSetting.ReadTimeout * time.Second

	ServerSetting.CrtPath = CurrentPath + ServerSetting.CrtPath
	ServerSetting.KeyPath = CurrentPath + ServerSetting.KeyPath

}

func GetCurrentPath() (string, error) {
	file, err := exec.LookPath(os.Args[0])
	if err != nil {
		return "", err
	}
	path, err := filepath.Abs(file)
	if err != nil {
		return "", err
	}
	if runtime.GOOS == "windows" {
		path = strings.Replace(path, "\\", "/", -1)
	}
	i := strings.LastIndex(path, "/")
	if i < 0 {
		return "", errors.New(`Can't find "/" or "\".`)
	}
	return path[0 : i+1], nil
}

func mapTo(section string, v interface{}) {
	err := cfg.Section(section).MapTo(v)
	if err != nil {
		log.Fatalf("Cfg.MapTo RedisSetting err: %v", err)
	}
}