package innerring

import (
	"context"

	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet"
	timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers"
	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/timer"
	"github.com/nspcc-dev/neo-go/pkg/util"
)

type (
	epochState interface {
		EpochCounter() uint64
		EpochDuration() uint64
	}

	newEpochHandler func()

	epochTimerArgs struct {
		newEpochHandlers []newEpochHandler

		epoch epochState // to specify which epoch to stop, and epoch duration
	}

	emitTimerArgs struct {
		ap *alphabet.Processor // to handle new emission tick

		emitDuration uint32 // in blocks
	}

	depositor func(context.Context) (util.Uint256, error)
	awaiter   func(context.Context, util.Uint256) error
)

func (s *Server) addBlockTimer(t *timer.BlockTimer) {
	s.blockTimers = append(s.blockTimers, t)
}

func (s *Server) startBlockTimers() error {
	for i := range s.blockTimers {
		if err := s.blockTimers[i].Reset(); err != nil {
			return err
		}
	}

	return nil
}

func (s *Server) tickTimers(h uint32) {
	for i := range s.blockTimers {
		s.blockTimers[i].Tick(h)
	}
}

func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer {
	return timer.NewBlockTimer(
		func() (uint32, error) {
			return uint32(args.epoch.EpochDuration()), nil
		},
		func() {
			for _, handler := range args.newEpochHandlers {
				handler()
			}
		},
	)
}

func newEmissionTimer(ctx context.Context, args *emitTimerArgs) *timer.BlockTimer {
	return timer.NewBlockTimer(
		timer.StaticBlockMeter(args.emitDuration),
		func() {
			args.ap.HandleGasEmission(ctx, timerEvent.NewAlphabetEmitTick{})
		},
	)
}