package crontab

import (
	"errors"
	"strconv"
	"strings"

	"474420502.top/eson/structure/priority_list"
	randomdata "github.com/Pallinder/go-randomdata"
)

type randLR struct {
	left, right int
}

// NodeCount 用于priority_list
type NodeCount struct {
	plist.Node
	randLR
}

type hInterval struct {
	PlanFailCount plist.PriorityList
	PlanTrueCount plist.PriorityList

	PlanFail []randLR
	PlanTrue []randLR

	Count      int
	ConstCount int
}

func (interval *hInterval) reset() {
	interval.Count = interval.ConstCount
}

// Compare NodeCount比较函数
func (rlr *NodeCount) Compare(v plist.INode) bool {
	return rlr.GetValue().(int) > v.GetValue().(int)
}

func parseIntervalFail(interval *hInterval, FN string) {
	scharIndex := strings.Index(FN, ">")
	if scharIndex != -1 {

		if FN[scharIndex+1] != '=' {
			panic(errors.New("= is not exist"))
		}

		fc := FN[0:scharIndex]
		flr := FN[scharIndex+2:]

		node := new(NodeCount)
		node.SetValue(getInt(fc[1:]))
		node.randLR = parseRandLR(flr)
		interval.PlanFailCount.Insert(node)
	} else {

		if FN[1] != '=' {
			panic(errors.New("= is not exist"))
		}

		fvalue := FN[2:]
		interval.PlanFail = append(interval.PlanFail, parseRandLR(fvalue))
	}
}

func parseIntervalSuccess(interval *hInterval, FN string) {
	scharIndex := strings.Index(FN, ">")
	if scharIndex != -1 {
		if FN[scharIndex+1] != '=' {
			panic(errors.New("= is not exist"))
		}

		tc := FN[0:scharIndex]
		tlr := FN[scharIndex+2:]

		node := new(NodeCount)
		node.SetValue(getInt(tc[1:]))
		node.randLR = parseRandLR(tlr)
		interval.PlanTrueCount.Insert(node)

	} else {

		if FN[1] != '=' {
			panic(errors.New("= is not exist"))
		}

		tvalue := FN[2:]
		interval.PlanTrue = append(interval.PlanTrue, parseRandLR(tvalue))
	}
}

func parseIntervalString(crontab string) []interface{} {
	var result []interface{}

	values := strings.Split(crontab, ",")
	for _, value := range values {
		interval := &hInterval{}

		// 次数
		valuesCounts := strings.Split(value, "x")
		switch len(valuesCounts) {
		case 1:
			interval.ConstCount = 1

		case 2:
			count, err := strconv.Atoi(valuesCounts[1])
			if err != nil {
				panic(err)
			}
			interval.ConstCount = count
		default:
			panic("valuesCounts error, the len is not in range")
		}

		// 统计失败与普通间隔值的数组
		failAndNormal := valuesCounts[0]

		valuesFN := strings.Split(failAndNormal, "|")

		for _, FN := range valuesFN {
			if FN == "" {
				continue
			}

			switch FN[0] {
			case 'f', 'F':
				parseIntervalFail(interval, FN)
			case 's', 'S':
				parseIntervalSuccess(interval, FN)
			default:
				FN = "s=" + FN
				parseIntervalSuccess(interval, FN)
			}
		}

		interval.reset()
		result = append(result, interval)
	}

	return result
}

func parseRandLR(lrvalue string) randLR {
	vlen := len(lrvalue)
	lastchar := lrvalue[vlen-1]

	lr := strings.Split(lrvalue, "-")
	switch len(lr) {
	case 1:
		lr := randLR{parseTimeValue(lr[0], lastchar), parseTimeValue(lr[0], lastchar)}
		return lr
	case 2:

		lr := randLR{parseTimeValue(lr[0], lastchar), parseTimeValue(lr[1], lastchar)}
		return lr
	default:
		panic("lr is error")
	}
}

// intervalPriorityListISecond 获取优先链表比较的值
func intervalPriorityListISecond(planlist *plist.PriorityList, count int) int {

	if planlist.Size() > 0 {
		node := new(NodeCount)
		node.SetValue(count)

		iwantNode := planlist.GetCompare(node)
		if iwantNode != nil {
			wantNode := iwantNode.(*NodeCount)
			lr := wantNode.randLR
			return randomdata.Number(lr.left, lr.right+1)
		}
	}

	return -1
}

func getInt(v string) int {
	vint, err := strconv.Atoi(v)
	if err != nil {
		panic(err)
	}
	return vint
}

func parseTimeValue(v string, lastchar byte) int {

	vlen := len(v)

	switch lastchar {
	case 's':
		return getInt(v[:vlen-1])
	case 'm':
		return getInt(v[:vlen-1]) * 60
	case 'h':
		return getInt(v[:vlen-1]) * 3600
	case 'd':
		return getInt(v[:vlen-1]) * 3600 * 24
	default:
		return getInt(v)
	}
}
