package components

import (
	"openquell/assets"
	"openquell/config"
	"time"

	"github.com/hajimehoshi/ebiten/v2"
)

const (
	Destruction = iota
	Idle
	Collision
	Moving
)

type AnimationTrigger int

type Animation interface {
	GetType() AnimationTrigger
	StartAnimation()
	StopAnimation()
	GetSprite() *ebiten.Image
	GetDuration() time.Duration
}

// implements the AnimationInterface
type StandardAnimation struct {
	Active        bool                     // animation is running
	Loop          bool                     // remove the entity if false, loop endless otherwise
	Index         int                      // where we are currently
	Sprites       []assets.AnimationSprite // each element contains the sprite and duration
	Width, Height int                      // single sprite measurements
	Timer         Timer
	Trigger       string
	Data          assets.TileAnimation
	Render        *Renderable
	Which         AnimationTrigger
}

func (animation *StandardAnimation) StartAnimation() {
	animation.Active = true
	animation.Timer.Start(0)
}

func (animation *StandardAnimation) StopAnimation() {
	animation.Active = false
}

func (animation *StandardAnimation) GetSprite() *ebiten.Image {
	return animation.Sprites[animation.Index].Sprite
}

func (animation *StandardAnimation) GetDuration() time.Duration {
	return animation.Sprites[animation.Index].Duration * time.Millisecond
}

func (animation *StandardAnimation) GetType() AnimationTrigger {
	return animation.Which
}

type CollisionAnimation struct {
	StandardAnimation
}

type IdleAnimation struct {
	StandardAnimation
}

type DestructionAnimation struct {
	StandardAnimation
}

type MovingAnimation struct {
	StandardAnimation
}

func (animation *DestructionAnimation) StartAnimation() {
	animation.Render.StopAnimations()
	animation.Render.Hidden = true
	animation.Active = true
	animation.Timer.Start(config.ANIMATION_STARTWAIT)
}

func (animation *IdleAnimation) StartAnimation() {
	animation.Render.StopAnimations()
	animation.Active = true
	animation.Loop = true
	animation.Timer.Start(0)
}

type Renderable struct {
	Pos         *Position // just for debugging, will not used as positiion!
	Image       *ebiten.Image
	DamageImage *ebiten.Image // FIXME: put into its own struct
	Damaged     int
	Shader      *ebiten.Shader
	Animations  map[AnimationTrigger]Animation
	Hidden      bool
}

func (render *Renderable) StopAnimations() {
	for _, animation := range render.Animations {
		animation.StopAnimation()
	}
}

func (render *Renderable) AddAnimation(which AnimationTrigger) {
	render.Animations = make(map[AnimationTrigger]Animation)

	switch which {
	case Idle:
		idle := &IdleAnimation{
			StandardAnimation: StandardAnimation{
				Which:  Idle,
				Render: render,
			},
		}
		render.Animations[Idle] = idle

	}
}
