package raftNode2

import (
	"PPOSUtils/utils"
	"encoding/json"
	"fmt"
)

const (
	DATATYPE_UUID = "uuid"
	DATATYPE_LOCK = "lock"
	DATATYPE_BASE = "base"
)

type FsmDataInterface interface {
	GetTree() string
	GetType() string
	GetKey() string
	GetData() interface{}
	GetPreDomain() string
}

//FsmData ...
type FsmData struct {
	Tr  string      `json:"tr"`
	Ke  string      `json:"ke"`
	Ty  string      `json:"ty"`
	Val interface{} `json:"val"`
}

func (that FsmData) GetType() string {
	return that.Ty
}

func (that FsmData) GetTree() string {
	return that.Tr
}

func (that FsmData) GetKey() string {
	return that.Ke
}

func (that FsmData) GetData() interface{} {
	return that.Val
}

type FsmUUidData struct {
	FsmData
	PreDomain string `json:"pre_domain"`
}

func (that FsmUUidData) GetPreDomain() string {
	return that.PreDomain
}

type FsmLockData struct {
	FsmData
	PreDomain string `json:"pre_domain"` //共享域
}

func (that FsmLockData) GetPreDomain() string {
	return that.PreDomain
}

type FsmKvData struct {
	FsmData
	PreDomain string `json:"pre_domain"` //过期时间
}

func (that FsmKvData) GetPreDomain() string {
	return that.PreDomain
}

type FsmQuery struct {
	Tree string `json:"tree"`
	Key  string `json:"key"`
}

type FsmEntry struct {
	Key string `json:"key"`
	Val string `json:"val"`
}

func createEntryKey(tree, key string) string {
	_val, _ := json.Marshal(FsmQuery{
		tree,
		key,
	})
	return string(_val)
}

func createEntry(data FsmDataInterface) []byte {
	_val, _ := json.Marshal(data)
	//为空则是删除
	if data.GetData() == nil {
		_val = []byte{}
	}
	_rs, _ := json.Marshal(FsmEntry{
		Key: createEntryKey(data.GetTree(), data.GetKey()),
		Val: string(_val),
	})
	return _rs
}

func parseEntry(data []byte) (FsmDataInterface, error) {
	//_fsmEntry := &FsmEntry{}
	//if _err := json.Unmarshal(data, &_fsmEntry); _err != nil {
	//	return nil, _err
	//}
	_mp := map[string]interface{}{}
	if _err := json.Unmarshal(data, &_mp); _err != nil {
		return nil, _err
	}
	return parseData(_mp), nil
}

func parseData(v interface{}) FsmDataInterface {
	switch _t := v.(type) {
	case FsmLockData:
		return _t
	case FsmUUidData:
		return _t
	case FsmKvData:
		return _t
	case map[string]interface{}:
		_type := utils.ToString(_t["ty"])
		fmt.Println(_type, "====== parseData ======", _t)
		switch _type {
		case DATATYPE_LOCK:
			_data := FsmLockData{
				FsmData: FsmData{
					Tr:  utils.ToString(_t["tr"], true),
					Ty:  _type,
					Ke:  utils.ToString(_t["ke"], true),
					Val: _t["val"],
				},
				PreDomain: utils.ToString(_t["pre_domain"], true),
			}
			return _data
		case DATATYPE_UUID:
			_data := FsmUUidData{
				FsmData: FsmData{
					Tr:  utils.ToString(_t["tr"], true),
					Ty:  _type,
					Ke:  utils.ToString(_t["ke"], true),
					Val: _t["val"],
				},
				PreDomain: utils.ToString(_t["pre_domain"], true),
			}
			return _data
		case DATATYPE_BASE:
			_data := FsmKvData{
				FsmData: FsmData{
					Tr:  utils.ToString(_t["tr"], true),
					Ty:  _type,
					Ke:  utils.ToString(_t["ke"], true),
					Val: _t["val"],
				},
				PreDomain: utils.ToString(_t["pre_domain"], true),
			}
			return _data
		}
	}
	return nil
}
