package elements

import (
	"image"
	"image/color"
	"math"
	"mover/assets"
	"mover/gamedata"

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

type FlyEye struct {
	Sprite     *ebiten.Image
	Maks       *ebiten.Image
	MaksDest   *ebiten.Image
	position   gamedata.Coordinates
	target     gamedata.Coordinates
	state      gamedata.EnemyState
	cycle      int
	dyingcount int
	health     int
	hit        bool
	touched    bool
	toggle     bool
	sploding   bool
}

func NewFlyEye() *FlyEye {
	f := &FlyEye{
		Sprite:     ebiten.NewImage(46, 46),
		Maks:       ebiten.NewImage(48, 48),
		MaksDest:   ebiten.NewImage(48, 48),
		health:     0,
		cycle:      0,
		dyingcount: 0,
		hit:        false,
		touched:    false,
		toggle:     false,
		sploding:   false,
	}
	f.Maks.Fill(color.White)
	return f
}

func (f *FlyEye) Update() error {

	//close loop on target
	if f.state <= gamedata.EnemyStateHit {
		dx := f.target.X - f.position.X
		dy := f.target.Y - f.position.Y
		if math.Abs(dx) > 3 || math.Abs(dy) > 3 {
			angle := math.Atan2(dy, dx)

			f.position.X += math.Cos(angle) * 3
			f.position.Y += math.Sin(angle) * 3
		}
	}

	if f.state == gamedata.EnemyStateDying {
		f.dyingcount++
	}

	f.cycle++

	return nil
}

func (f *FlyEye) Draw() {
	f.Sprite.Clear()
	f.MaksDest.Clear()

	idx := (f.cycle / 8) % 4

	y0 := 0
	y1 := 48
	x0 := 48 * idx
	x1 := x0 + 48

	switch f.state {
	case gamedata.EnemyStateDefault:
		if !f.toggle {
			f.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeNormal].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
		} else {
			f.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeDamaged].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
		}
	case gamedata.EnemyStateDying:
		//after some condition, set to exploding
		if (f.cycle/5)%2 == 0 {

			f.MaksDest.DrawImage(assets.ImageBank[assets.FlyEyeDamaged].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
			op := &ebiten.DrawImageOptions{}
			op.GeoM.Reset()
			op.Blend = ebiten.BlendSourceAtop
			f.MaksDest.DrawImage(f.Maks, op)
			f.Sprite.DrawImage(f.MaksDest, nil)

		} else {
			f.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeDamaged].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
		}
		if f.dyingcount >= 31 {
			f.cycle = 0
			f.state = gamedata.EnemyStateExploding
		}
	case gamedata.EnemyStateExploding:
		f.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeDying].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
		if idx == 3 {
			f.state = gamedata.EnemyStateDead
		}
	}
}

func (f *FlyEye) GetPosition() gamedata.Coordinates {
	return f.position
}

func (f *FlyEye) SetTarget(p gamedata.Coordinates) {
	f.target = p
}

func (f *FlyEye) GetSprite() *ebiten.Image {
	return f.Sprite
}

func (f *FlyEye) SetHit() {
	f.hit = true
	f.state = gamedata.EnemyStateDying
	f.cycle = 0
	f.health--
}

func (f *FlyEye) IsTouched() bool {
	return f.touched
}

func (f *FlyEye) SetTouched() {
	f.touched = true
}

func (f *FlyEye) ClearTouched() {
	f.touched = false
}

func (f *FlyEye) SetToggle() {
	f.toggle = !f.toggle
}

func (f *FlyEye) IsToggled() bool {
	return f.toggle
}

func (f *FlyEye) GetEnemyState() gamedata.EnemyState {
	return f.state
}

func (f *FlyEye) SetPosition(p gamedata.Coordinates) {
	f.position = p
}

func (f *FlyEye) ExplosionInitiated() bool {
	return f.sploding
}

func (f *FlyEye) SetExplosionInitiated() {
	f.sploding = true
}

func (f *FlyEye) Health() int {
	//health bars reserved for special enemies, flyeye is a one
	//hitter so returning zero ensure no health bar is rendered
	return f.health
}

func (f *FlyEye) MaxHealth() int {
	return 1
}

func (f *FlyEye) GetAngle() float64 {
	return 0
}
