package ants

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

//NewJsonParse ...
func NewJsonParse(param []byte, required ...interface{}) (JsonParams, error) {
	_jsonParams := map[string]interface{}{}
	if _err := json.Unmarshal(param, &_jsonParams); _err != nil {
		return nil, _err
	}
	if len(required) > 0 {
		for _, _v := range required {
			switch _t := _v.(type) {
			case []string:
				for _, _paramName := range _t {
					if _, _ok := _jsonParams[_paramName]; !_ok {
						return _jsonParams, errors.New("pamams not fount [" + _paramName + "]")
					}
				}
			case string:
				if _, _ok := _jsonParams[_t]; !_ok {
					return _jsonParams, errors.New("pamams not fount [" + _t + "]")
				}
			}

		}
	}
	return _jsonParams, nil
}

type JsonParams map[string]interface{}

func (that JsonParams) GetString(key string) string {
	_data, _ok := that[key]
	if !_ok {
		return ""
	}
	return that.toString(_data, true)
}

func (that JsonParams) Set(key string, value interface{}) JsonParams {
	that[key] = value
	return that
}

func (that JsonParams) Marshal(key string, value interface{}) []byte {
	_bytes, _ := json.Marshal(that)
	return _bytes
}

//toString ...
func (that JsonParams) toString(d interface{}, floatDiscard ...bool) string {
	switch n := d.(type) {
	case int:
		return strconv.FormatInt(int64(n), 10)
	case int8:
		return strconv.FormatInt(int64(n), 10)
	case int16:
		return strconv.FormatInt(int64(n), 10)
	case int32:
		return strconv.FormatInt(int64(n), 10)
	case int64:
		return strconv.FormatInt(n, 10)
	case uint8:
		return strconv.FormatInt(int64(n), 10)
	case uint16:
		return strconv.FormatInt(int64(n), 10)
	case uint32:
		return strconv.FormatInt(int64(n), 10)
	case uint64:
		return strconv.FormatInt(int64(n), 10)
	case string:
		_str := n
		if len(floatDiscard) > 0 && floatDiscard[0] {
			_str = strings.TrimSuffix(_str, ".00")
		}
		return _str
	case float32:
		_str := strconv.FormatFloat(float64(n), 'f', 2, 64)
		if len(floatDiscard) > 0 && floatDiscard[0] {
			_str = strings.TrimSuffix(_str, ".00")
		}
		return _str
	case float64:
		_str := strconv.FormatFloat(n, 'f', 2, 64)
		if len(floatDiscard) > 0 && floatDiscard[0] {
			_str = strings.TrimSuffix(_str, ".00")
		}
		return _str
	case []byte:
		_str := string(n)
		if len(floatDiscard) > 0 && floatDiscard[0] {
			_str = strings.TrimSuffix(_str, ".00")
		}
		return _str
	case error:
		return n.Error()
	case bool:
		if n {
			return "1"
		}
		return "0"
	}
	return "0"
}
