package raftNode

import (
	"PPOSUtils/utils"
	"strings"
	"sync"
)

var modulusMap = map[int64]int64{
	0: 0,
	1: 0,
	2: 0,
	3: 0,
	4: 0,
	5: 0,
	6: 0,
	7: 0,
	8: 0,
	9: 0,
}

func SetUUidModulus(v string) {
	_slice := strings.Split(v, "|")
	for _, _v := range _slice {
		_m := utils.ToInt64(_v)
		if _, _ok := modulusMap[_m]; _ok {
			modulusMap[_m] = 1
		}
	}
}

type uidCacheAction struct {
	uidMap  map[string]uidData //内存游标
	uidLock sync.Mutex         //锁
}

func (that *uidCacheAction) Clear() {
	that.uidLock.Lock()
	defer that.uidLock.Unlock()
	that.uidMap = map[string]uidData{}
}

func (that *uidCacheAction) IsExist(key string) bool {
	that.uidLock.Lock()
	defer that.uidLock.Unlock()
	_, _ok := that.uidMap[key]
	return _ok
}

func (that *uidCacheAction) InitStart(name string, id, preDomain int64) {
	that.initID(name, id, preDomain)
	uidAsyncSave.initUidUpdate(name, id, preDomain)
}

func (that *uidCacheAction) initID(name string, id, preDomain int64) {
	that.uidLock.Lock()
	defer that.uidLock.Unlock()
	_newData := uidData{
		name:      name,
		uid:       id,
		preDomain: preDomain,
	}
	that.uidMap[name] = _newData
}

//newID id缓存（最新的id值）
func (that *uidCacheAction) newID(name string, id, preDomain int64, step ...int64) (int64, int64) {
	that.uidLock.Lock()
	defer that.uidLock.Unlock()
	//初始值
	_newID := id
	_preDomain := preDomain
	//
	_data, _ok := that.uidMap[name]
	log.Debug("[newID] params:", name, id, preDomain, step)
	if _ok {
		if _data.preDomain >= _preDomain {
			//历史"前置域" > 传入"前置域" ： id 累加
			_preDomain = _data.preDomain
			_newID = modulusID(_data.uid, step...)
		} else {
			//传入"前置域" > 历史"前置域" ： id 从初始值开始
			//但考虑到"前置域"不合规的问题，做如下兼容处理：
			if _data.preDomain+_data.uid > _preDomain+_newID {
				_preDomain = _data.preDomain
				_newID = modulusID(_data.uid, step...)
			}
			//否则，传入"前置域"+ id 从初始值开始。。。不用处理
		}
	}
	log.Debug("[newID] modulusID success, id:", _newID)
	//
	_newData := uidData{
		name:      name,
		uid:       _newID,
		preDomain: _preDomain,
	}
	that.uidMap[name] = _newData
	//异步落地到raft分布式存储里
	//uidAsyncSave.uidUpdateSign(_newData)
	log.Debug("[newID] uidUpdateSign success")
	return _newID, _preDomain
}

func modulusID(id int64, step ...int64) int64 {
	//追加1
	_step := int64(1)
	if len(step) > 0 {
		_step = step[0]
	}
	_i := int64(0)
	for {
		if _i >= _step {
			return id
		}
		id = id + 1
		_mod := id % 10
		if _modStatus, _ := modulusMap[_mod]; _modStatus == 1 {
			//return id
			_i++
		}
	}
}
