/**
	只适用于一天24小时开奖的情况，0->1
**/
package gametimer

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/gookit/event"
	"github.com/sirupsen/logrus"
	"gogs.daxia.dev/huanan/pkg.daxia.dev/intutils"
	"gogs.daxia.dev/huanan/pkg.daxia.dev/time_utils"
)

const (
	EventTimerStart = "EventTimerStart"
	EventTimerStop  = "EventTimerStop"
)

type GameTimer struct {
	baseTime    time.Time
	baseName    string
	totalSecond int
	stopSecond  int

	currentEvent string
}

func NewGameTimer(baseName string, baseTime time.Time, totalSecond, stopSecond int) *GameTimer {
	if stopSecond > totalSecond {
		panic("stop second > total second")
	}

	if (1440*60)%totalSecond != 0 {
		panic("total second不能被整除")
	}

	instance := &GameTimer{
		baseTime: baseTime,
		baseName: baseName,

		totalSecond: totalSecond,
		stopSecond:  stopSecond,
	}

	instance.currentEvent = ""
	go instance.start()

	return instance
}

func (p *GameTimer) start() {
	for {
		<-time.After(1 * time.Second)
		err := p.doWork()
		if err != nil {
			logrus.Error(err)
		}
	}
}

func (p *GameTimer) doWork() error {
	currentEvent := p.GetCurrentEvent()
	if p.currentEvent == currentEvent {
		return nil
	}

	p.currentEvent = currentEvent
	event.MustFire(p.currentEvent, event.M{})

	return nil
}

func (p *GameTimer) GetCurrentEvent() string {
	secondFromBase := time_utils.TimeNowInCN().Unix() - p.baseTime.Unix()
	//180 [0 - 180]
	secondInRange := secondFromBase % int64(p.totalSecond)
	if secondInRange < int64(p.stopSecond) {
		return p.GetEvent(EventTimerStart)
	}

	return p.GetEvent(EventTimerStop)
}

func (p *GameTimer) GetIssueByTime(timeIssue time.Time) int64 {
	secondFromBase := timeIssue.Unix() - p.baseTime.Unix()
	issue := secondFromBase / int64(p.totalSecond)

	return (issue + 1)
}

func (p *GameTimer) GetIssueStrByTime(timeIssue time.Time) string {
	return p.GetIssueStr(p.GetIssueByTime(timeIssue))
}

func (p *GameTimer) GetIssueStr(issue int64) string {
	timestamp := p.baseTime.Unix() + int64(issue-1)*int64(p.totalSecond)
	timeIssue := time.Unix(timestamp, 0)

	timeIssueCN := timeIssue.In(time_utils.GetCNZone())

	totalIssueOnDay := (1440 * 60) / p.totalSecond
	maxSize := intutils.IntSize(totalIssueOnDay)
	fmtStr := fmt.Sprintf("0%dd", maxSize)

	todayIssue := p.GetIssueFromTodayZero(timeIssueCN)

	return timeIssueCN.Format("2006-01-02") + " " + fmt.Sprintf("%"+fmtStr, todayIssue)
}

func (p *GameTimer) GetIssueFromStr(issueStr string) (int64, error) {
	timeIssue, err := p.GetIssueTime(issueStr)
	if err != nil {
		return 0, err
	}

	fmt.Println(timeIssue)
	fmt.Println(p.baseTime)

	return 1 + ((timeIssue.Unix() - p.baseTime.Unix()) / int64(p.totalSecond)), nil
}

func (p *GameTimer) GetIssueTime(issueStr string) (*time.Time, error) {
	issueTimeSplit := strings.Split(issueStr, " ")
	if len(issueTimeSplit) != 2 {
		return nil, errors.New("期号格式错误")
	}

	timeIssue, err := time.ParseInLocation("2006-01-02", issueTimeSplit[0], time_utils.GetCNZone())
	if err != nil {
		return nil, err
	}

	numStr := strings.TrimLeft(issueTimeSplit[1], "0")

	issueInt, err := strconv.Atoi(numStr)
	if err != nil {
		return nil, err
	}

	timeIssue = timeIssue.Add(time.Duration(issueInt-1) * time.Duration(p.totalSecond) * time.Second)

	return &timeIssue, nil
}

func (p *GameTimer) GetIssueTimeInt(issue int64) (*time.Time, error) {
	issueStr := p.GetIssueStr(issue)
	return p.GetIssueTime(issueStr)
}

func (p *GameTimer) GetBaseTime() time.Time {
	return p.baseTime
}

func (p *GameTimer) GetIssueFromTodayZero(timeIssue time.Time) int64 {
	secondFromBase := timeIssue.Unix() - time_utils.GetZeroTime(timeIssue).Unix()

	issue := secondFromBase / int64(p.totalSecond)

	return issue + 1
}

func (p GameTimer) GetEvent(eventName string) string {
	return p.baseName + eventName
}
