package common

import (
	"encoding/json"
	"errors"
	"math"
	"strconv"
	"time"
)

//仅限于hotime.Slice
func ObjToMap(obj interface{}, e ...*Error) Map {
	var err error
	var v Map

	if obj == nil {
		v = nil
		err = errors.New("没有合适的转换对象！")
	} else {
		switch obj.(type) {
		case Map:
			v = obj.(Map)
		case map[string]interface{}:
			v = obj.(map[string]interface{})
		case string:
			v = Map{}
			e := json.Unmarshal([]byte(obj.(string)), &v)
			if e != nil {
				err = errors.New("没有合适的转换对象！" + e.Error())
				v = nil
			}
		default:
			data, err := json.Marshal(obj)
			if err != nil {
				err = errors.New("没有合适的转换对象！" + err.Error())
				v = nil
			}
			v = Map{}
			e := json.Unmarshal(data, &v)
			if e != nil {
				err = errors.New("没有合适的转换对象！" + e.Error())
				v = nil
			}

		}
	}
	if len(e) != 0 {
		e[0].SetError(err)
	}
	return v
}

func ObjToMapArray(obj interface{}, e ...*Error) []Map {
	s := ObjToSlice(obj, e...)
	res := []Map{}
	for i := 0; i < len(s); i++ {
		res = append(res, s.GetMap(i))
	}
	return res
}

//仅限于hotime.Slice
func ObjToSlice(obj interface{}, e ...*Error) Slice {
	var err error
	var v Slice

	if obj == nil {
		v = nil
		err = errors.New("没有合适的转换对象！")
	} else {
		switch obj.(type) {
		case Slice:
			v = obj.(Slice)
		case []interface{}:
			v = obj.([]interface{})
		case []string:
			v = Slice{}
			for i := 0; i < len(obj.([]string)); i++ {
				v = append(v, obj.([]string)[i])
			}
		case string:
			v = Slice{}
			err = json.Unmarshal([]byte(obj.(string)), &v)

		default:
			v = Slice{}
			var data []byte
			data, err = json.Marshal(obj)
			err = json.Unmarshal(data, &v)
		}
	}

	if len(e) != 0 {
		e[0].SetError(err)
	}

	return v
}

func ObjToTime(obj interface{}, e ...*Error) *time.Time {

	tInt := ObjToInt64(obj)
	//字符串类型，只支持标准mysql datetime格式
	if tInt == 0 {
		tStr := ObjToStr(obj)

		if len(tStr) > 18 {
			t, e := time.Parse("2006-01-02 15:04:05", tStr)
			if e == nil {
				return &t
			}
		} else if len(tStr) > 15 {
			t, e := time.Parse("2006-01-02 15:04", tStr)
			if e == nil {
				return &t
			}
		} else if len(tStr) > 12 {
			t, e := time.Parse("2006-01-02 15", tStr)
			if e == nil {
				return &t
			}
		} else if len(tStr) > 9 {
			t, e := time.Parse("2006-01-02", tStr)
			if e == nil {
				return &t
			}
		} else if len(tStr) > 6 {
			t, e := time.Parse("2006-01", tStr)
			if e == nil {
				return &t
			}
		}

	}

	//纳秒级别
	if len(ObjToStr(tInt)) > 16 {
		t := time.Time{}.Add(time.Nanosecond * time.Duration(tInt))
		return &t
		//微秒级别
	} else if len(ObjToStr(tInt)) > 13 {
		t := time.Time{}.Add(time.Microsecond * time.Duration(tInt))
		return &t
		//毫秒级别
	} else if len(ObjToStr(tInt)) > 10 {
		t := time.Time{}.Add(time.Millisecond * time.Duration(tInt))
		return &t
		//秒级别
	} else if len(ObjToStr(tInt)) > 9 {
		t := time.Time{}.Add(time.Second * time.Duration(tInt))
		return &t
	} else if len(ObjToStr(tInt)) > 3 {
		t, e := time.Parse("2006", ObjToStr(tInt))
		if e == nil {
			return &t
		}
	}

	return nil
}

func ObjToFloat64(obj interface{}, e ...*Error) float64 {
	var err error
	v := float64(0)

	if obj == nil {

		err = errors.New("没有合适的转换对象！")
	} else {

		switch obj.(type) {
		case int:
			v = float64(obj.(int))
		case int64:
			v = float64(obj.(int64))
		case string:
			value, e := strconv.ParseFloat(obj.(string), 64)
			if e != nil {
				v = float64(0)
				err = e
			} else {
				v = value
			}
		case float64:
			v = obj.(float64)
		case float32:
			v = float64(obj.(float32))
		case uint8:
			value, e := strconv.ParseFloat(obj.(string), 64)
			if e != nil {
				v = float64(0)
				err = e
			} else {
				v = value
			}
		default:
			v = float64(0)
			err = errors.New("没有合适的转换对象！")
		}
	}

	if math.IsNaN(v) {
		err = errors.New("float64 is NaN")
		v = 0
	}
	if math.IsInf(v, 0) {
		err = errors.New("float64 is Inf")
		v = 0
	}
	if len(e) != 0 {
		e[0].SetError(err)
	}

	return v
}

//向上取整
func ObjToCeilInt64(obj interface{}, e ...*Error) int64 {
	f := ObjToCeilFloat64(obj, e...)
	return ObjToInt64(math.Ceil(f))

}

//向上取整
func ObjToCeilFloat64(obj interface{}, e ...*Error) float64 {
	f := ObjToFloat64(obj, e...)
	return math.Ceil(f)

}

//向上取整
func ObjToCeilInt(obj interface{}, e ...*Error) int {
	f := ObjToCeilFloat64(obj, e...)
	return ObjToInt(f)

}

func ObjToInt64(obj interface{}, e ...*Error) int64 {
	var err error
	v := int64(0)

	if obj == nil {

		err = errors.New("没有合适的转换对象！")
	} else {
		switch obj.(type) {
		case int:
			v = int64(obj.(int))
		case int64:
			v = obj.(int64)
		case string:
			value, e := StrToInt(obj.(string))
			if e != nil {
				v = int64(0)
				err = e
			} else {
				v = int64(value)
			}
		case uint8:
			value, e := StrToInt(obj.(string))
			if e != nil {
				v = int64(0)
				err = e
			} else {
				v = int64(value)
			}
		case float64:
			v = int64(obj.(float64))
		case float32:
			v = int64(obj.(float32))
		default:
			v = int64(0)
			err = errors.New("没有合适的转换对象！")
		}
	}
	if len(e) != 0 {
		e[0].SetError(err)
	}
	return v
}

func ObjToInt(obj interface{}, e ...*Error) int {
	v := ObjToInt64(obj, e...)
	return int(v)
}

func ObjToBool(obj interface{}, e ...*Error) bool {
	var err error
	v := false

	if obj == nil {

		err = errors.New("没有合适的转换对象！")
	} else {
		switch obj.(type) {
		case bool:
			v = obj.(bool)
		default:
			toInt := ObjToInt(obj)
			if toInt != 0 {
				v = true
			}
			err = errors.New("没有合适的转换对象！")
		}
	}
	if len(e) != 0 {
		e[0].SetError(err)
	}
	return v
}

func ObjToStr(obj interface{}) string {
	//	fmt.Println(reflect.ValueOf(obj).Type().String() )
	str := ""
	if obj == nil {
		return str
	}
	switch obj.(type) {
	case int:
		str = strconv.Itoa(obj.(int))
	case uint8:
		str = obj.(string)
	case int64:
		str = strconv.FormatInt(obj.(int64), 10)
	case []byte:
		str = string(obj.([]byte))
	case string:
		str = obj.(string)
	case float64:
		str = strconv.FormatFloat(obj.(float64), 'f', -1, 64)
	default:
		strbte, err := json.MarshalIndent(obj, "", "\t")

		if err == nil {
			str = string(strbte)
		}

	}

	return str
}

//转换为Map
func StrToMap(string string) Map {
	data := Map{}
	data.JsonToMap(string)

	return data
}

//转换为Slice
func StrToSlice(string string) Slice {

	data := ObjToSlice(string)

	return data
}

//字符串数组: a1,a2,a3转["a1","a2","a3"]
func StrArrayToJsonStr(a string) string {

	if len(a) > 2 {
		if a[0] == ',' {
			a = Substr(a, 1, len(a)-1)
		}
		if a[len(a)-1] == ',' {
			a = Substr(a, 0, len(a)-1)
		}
		//a = strings.Replace(a, ",", `,`, -1)
		a = `[` + a + `]`
	} else {
		a = "[]"
	}
	return a
}

//字符串数组: a1,a2,a3转["a1","a2","a3"]
func JsonStrToStrArray(a string) string {
	//a = strings.Replace(a, `"`, "", -1)
	if len(a) != 0 {
		a = Substr(a, 1, len(a)-2)
	}

	return "," + a + ","
}

//字符串转int
func StrToInt(s string) (int, error) {
	i, err := strconv.Atoi(s)
	return i, err

}
