package loadmodule

import (
	"errors"
	"gateway/common/logs"
	"github.com/gogf/gf/v2/os/gctx"
	"net/url"
	"strconv"
	"strings"
)

type WeightRoundRobinProxy struct {
	curIndex int
	rss      []*WeightNode
	rsw      []int
}

type WeightNode struct {
	addr            *url.URL
	weight          int //权重值
	currentWeight   int //节点当前权重
	effectiveWeight int //有效权重
}

func (r *WeightRoundRobinProxy) Add(param string) error {
	params := strings.Split(param, "|")
	if len(params) != 2 {
		return errors.New("param len need 2")
	}
	parInt, err := strconv.ParseInt(params[1], 10, 64)
	if err != nil {
		return err
	}
	remoteUrl, err := url.Parse(strings.TrimSpace(params[0]))
	if err != nil {
		return err
	}

	node := &WeightNode{addr: remoteUrl, weight: int(parInt)}
	node.effectiveWeight = node.weight
	r.rss = append(r.rss, node)
	return nil
}

func (r *WeightRoundRobinProxy) Next() *url.URL {
	if len(r.rss) == 1 {
		return r.rss[0].addr
	}
	total := 0
	var best *WeightNode
	for i := 0; i < len(r.rss); i++ {
		w := r.rss[i]
		//step 1 统计所有有效权重之和
		total += w.effectiveWeight

		//step 2 变更节点临时权重为的节点临时权重+节点有效权重
		w.currentWeight += w.effectiveWeight

		//step 3 有效权重默认与权重相同，通讯异常时-1, 通讯成功+1，直到恢复到weight大小
		if w.effectiveWeight < w.weight {
			w.effectiveWeight++
		}
		//step 4 选择最大临时权重点节点
		if best == nil || w.currentWeight > best.currentWeight {
			best = w
		}
	}
	if best == nil {
		logs.GInfo.Info(gctx.New(), "WeightRoundRobinProxy 获取权重异常 ")
		return r.rss[0].addr
	}
	//step 5 变更临时权重为 临时权重-有效权重之和
	best.currentWeight -= total
	return best.addr
}

func (r *WeightRoundRobinProxy) Get() *url.URL {
	return r.Next()
}

func (r *WeightRoundRobinProxy) Len() int {
	return len(r.rss)
}

func (r *WeightRoundRobinProxy) Update() {

}
