// ************************************
// @package: app_environment
// @description: 模拟进程级别的环境变量功能
// 注意，此文件非线程安全，请注意使用，设计上是在init的过程中存放，在运行过程中只读取
// @author:  byron
// @revision history:
// @create date: 2022-01-25 16:54:47
// ************************************
package app_environment

import (
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
)

var (
	kv map[string]string
)

func init() {
	kv = make(map[string]string)
}

// Reset
// @description: 重置环境变量
// parameter:
//		@kvmap:
// return:
//		@error:
func Reset(kvmap map[string]string) error {
	if kvmap == nil {
		return fmt.Errorf("app_environment.Reset 不允许使用nil map做参数")
	}

	kv = kvmap
	return nil
}

// Set
// @description: 设置环境变量，如果存在，会返回error；如果要覆盖，请使用 SetForCover 方法
// parameter:
//		@k:key
//		@v:value
// return:
//		@error:如果已经存在，则返回error
func Set(k, v string) error {
	if _, eixsts := kv[k]; eixsts {
		return errors.New(fmt.Sprintf("已经存在k=%s的缓存", k))
	}

	kv[k] = v

	return nil
}

// SetMap
// @description: 设置环境变量，如果存在，会返回error；如果要覆盖，请使用 SetForCoverMap 方法
// parameter:
//		@kvmap:
// return:
//		@error:
func SetMap(kvmap map[string]string) error {
	for k, v := range kvmap {
		if err := Set(k, v); err != nil {
			return err
		}
	}

	return nil
}

// SetForCover
// @description: 设置环境变量,如果存在，则覆盖
// parameter:
//		@k:key
//		@v:value
// return:
func SetForCover(k, v string) {
	kv[k] = v
}

// SetForCoverMap
// @description: 设置环境变量,如果存在，则覆盖
// parameter:
//		@kvmap:
// return:
func SetForCoverMap(kvmap map[string]string) {
	for k, v := range kvmap {
		SetForCover(k, v)
	}
}

// SetForNoExists
// @description: 如果不存在，则设置
// parameter:
//		@k:key
//		@v:value
// return:
func SetForNoExists(k, v string) {
	if _, eixsts := kv[k]; eixsts {
		return
	}

	kv[k] = v
}

// SetForNoExistsMap
// @description: 如果不存在，则设置
// parameter:
//		@kvmap:要设置的字典
// return:
func SetForNoExistsMap(kvmap map[string]string) {
	for k, v := range kvmap {
		SetForNoExists(k, v)
	}
}

// GetAll
// @description: 获取所有的环境变量
// parameter:
// return:
//		@map[string]string:环境变量内容
func GetAll() map[string]string {
	tempKv := make(map[string]string, len(kv))
	for k, v := range kv {
		tempKv[k] = v
	}

	return tempKv
}

// Get
// @description: 获取环境变量
// parameter:
//		@k:配置项
// return:
//		@string:value
//		@bool:是否存在对应的值
func Get(k string) (string, bool) {
	v, exists := kv[k]

	return v, exists
}

// GetOrDefault
// @description: 获取环境变量,未配置情况下使用默认值
// parameter:
//		@k:配置项
//		@defaultValue:默认值
// return:
//		@string:结果值
func GetOrDefault(k string, defaultValue string) string {
	v, ok := Get(k)
	if !ok {
		return defaultValue
	}

	return v
}

// GetInt
// @description: 获取环境变量
// parameter:
//		@k:key
// return:
//		@int:value
//		@bool:是否存在对应的值
//		@error:配置值解析失败时返回
func GetInt(k string) (int, bool, error) {
	v, isok := Get(k)
	if isok == false {
		return 0, false, nil
	}

	i, err := strconv.Atoi(v)
	if err != nil {
		return 0, true, err
	}

	return i, true, nil
}

// GetIntOrDefault
// @description: 获取环境变量,未配置情况下使用默认值
// parameter:
//		@k:配置项
//		@defaultValue:默认值
// return:
//		@int:结果值
//		@error:配置值解析失败时返回
func GetIntOrDefault(k string, defaultValue int) (int, error) {
	val, ok, err := GetInt(k)
	if err != nil || !ok {
		return defaultValue, err
	}

	return val, nil
}

// GetInt32
// @description: 获取环境变量
// parameter:
//		@k:key
// return:
//		@int:value
//		@bool:是否存在对应的值
//		@error:配置值解析失败时返回
func GetInt32(k string) (int32, bool, error) {
	v, isok := Get(k)
	if isok == false {
		return 0, false, nil
	}

	i, err := strconv.ParseInt(v, 10, 32)
	if err != nil {
		return 0, true, err
	}

	return int32(i), true, nil
}

// GetInt32OrDefault
// @description: 获取环境变量,未配置情况下使用默认值
// parameter:
//		@k:配置项
//		@defaultValue:默认值
// return:
//		@int:结果值
//		@error:配置值解析失败时返回
func GetInt32OrDefault(k string, defaultValue int32) (int32, error) {
	val, ok, err := GetInt32(k)
	if err != nil || !ok {
		return defaultValue, err
	}

	return val, nil
}

// GetInt64
// @description: 获取环境变量
// parameter:
//		@k:key
// return:
//		@int64:value
//		@bool:是否存在对应的值
//		@error:过程是否出错
func GetInt64(k string) (int64, bool, error) {
	v, isok := Get(k)
	if isok == false {
		return 0, false, nil
	}

	i64, err := strconv.ParseInt(v, 10, 64)
	if err != nil {
		return 0, true, err
	}

	return i64, true, nil
}

// GetInt64OrDefault
// @description: 获取环境变量,未配置情况下使用默认值
// parameter:
//		@k:配置项
//		@defaultValue:默认值
// return:
//		@int:结果值
//		@error:配置值解析失败时返回
func GetInt64OrDefault(k string, defaultValue int64) (int64, error) {
	val, ok, err := GetInt64(k)
	if err != nil || !ok {
		return defaultValue, err
	}

	return val, nil
}

// GetFloat32
// @description: 获取环境变量
// parameter:
//		@k:key
// return:
//		@int64:value
//		@bool:是否存在对应的值
//		@error:过程是否出错
func GetFloat32(k string) (float32, bool, error) {
	v, isok := Get(k)
	if isok == false {
		return 0, false, nil
	}

	f64, err := strconv.ParseFloat(v, 32)
	if err != nil {
		return 0, true, err
	}

	return float32(f64), true, nil
}

// GetFloat32OrDefault
// @description: 获取环境变量,未配置情况下使用默认值
// parameter:
//		@k:配置项
//		@defaultValue:默认值
// return:
//		@int:结果值
//		@error:配置值解析失败时返回
func GetFloat32OrDefault(k string, defaultValue float32) (float32, error) {
	val, ok, err := GetFloat32(k)
	if err != nil || !ok {
		return defaultValue, err
	}

	return val, nil
}

// GetFloat64
// @description: 获取环境变量
// parameter:
//		@k:key
// return:
//		@int64:value
//		@bool:是否存在对应的值
//		@error:过程是否出错
func GetFloat64(k string) (float64, bool, error) {
	v, isok := Get(k)
	if isok == false {
		return 0, false, nil
	}

	f64, err := strconv.ParseFloat(v, 64)
	if err != nil {
		return 0, true, err
	}

	return f64, true, nil
}

// GetFloat64OrDefault
// @description: 获取环境变量,未配置情况下使用默认值
// parameter:
//		@k:配置项
//		@defaultValue:默认值
// return:
//		@int:结果值
//		@error:配置值解析失败时返回
func GetFloat64OrDefault(k string, defaultValue float64) (float64, error) {
	val, ok, err := GetFloat64(k)
	if err != nil || !ok {
		return defaultValue, err
	}

	return val, nil
}

// GetBool
// @description: 获取环境变量
// parameter:
//		@k:key
// return:
//		@bool:value
//		@bool:是否存在对应的值
//		@error:过程是否出错
func GetBool(k string) (bool, bool, error) {
	v, isok := Get(k)
	if isok == false {
		return false, false, nil
	}

	i, err := strconv.ParseBool(v)
	if err != nil {
		return false, true, err
	}

	return i, true, nil
}

// GetBoolOrDefault
// @description: 获取环境变量,未配置情况下使用默认值
// parameter:
//		@k:配置项
//		@defaultValue:默认值
// return:
//		@int:结果值
//		@error:配置值解析失败时返回
func GetBoolOrDefault(k string, defaultValue bool) (bool, error) {
	val, ok, err := GetBool(k)
	if err != nil || !ok {
		return defaultValue, err
	}

	return val, nil
}

// GetModel
// @description: 获取环境变量，并将内容序列化到obj对象中返回
// parameter:
//		@k:key
//		@obj:value
// return:
//		@bool:是否存在对应的值
//		@error:过程是否出错
func GetModel(k string, obj interface{}) (bool, error) {
	v, isok := Get(k)
	if isok == false {
		return false, nil
	}

	if err := json.Unmarshal([]byte(v), obj); err != nil {
		return true, err
	}

	return true, nil
}
