// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

package gesture

import (
	"encoding/json"
	"io/ioutil"
	"os"
	"strings"

	"github.com/linuxdeepin/go-lib/utils"
)

const (
	configSuffix     = "dde-daemon/gesture/conf.json"
	configPathEtc    = "/etc/" + configSuffix
	configPathShare  = "/usr/share/" + configSuffix
	overrideDirShare = "/usr/share/dde-daemon/gesture.d"
	overrideDirEtc   = "/etc/dde-daemon/gesture.d"
)

type Config struct {
	LongPressDistance float64 `json:"longpress_distance"`
	EdgeErrorLimit    int     `json:"edge_error_limit"`
	Verbose           int     `json:"verbose"`
}

func (c *Config) validate() {
	if c.LongPressDistance < 0 {
		logger.Warning("Invalid longpress_distance value, reset to 0")
		c.LongPressDistance = 5
	}
	if c.EdgeErrorLimit < 0 {
		logger.Warning("Invalid edge_error_limit value, reset to 0")
		c.EdgeErrorLimit = 3
	}
	if c.Verbose < 0 {
		logger.Warning("Invalid verbose value, reset to 0")
		c.Verbose = 0
	}
}

func loadConfig(filename string) (*Config, error) {
	contents, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	var conf Config
	err = json.Unmarshal(contents, &conf)
	if err != nil {
		return nil, err
	}

	loadDirConfig(overrideDirShare, &conf)
	loadDirConfig(overrideDirEtc, &conf)

	conf.validate()

	return &conf, nil
}

func loadDirConfig(dir string, conf *Config) {
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		if !os.IsNotExist(err) {
			logger.Warning("Failed to read override dir", dir, ":", err)
		}
		return
	}
	for _, fi := range files {
		if fi.IsDir() || !strings.HasSuffix(fi.Name(), ".json") {
			continue
		}
		filename := dir + "/" + fi.Name()
		contents, err := ioutil.ReadFile(filename)
		if err != nil {
			logger.Warning("Failed to read override config", filename, ":", err)
			continue
		}
		if err := json.Unmarshal(contents, conf); err != nil {
			logger.Warning("Failed to parse override config", filename, ":", err)
		}
	}
}

func getConfigPath() string {
	if utils.IsFileExist(configPathEtc) {
		return configPathEtc
	}
	return configPathShare
}
