package widgets

import (
	"fmt"
	"image/color"

	"tetris/engine/core"
	"tetris/engine/input"
	"tetris/engine/render"
	"tetris/game/ui/base"

	rl "github.com/gen2brain/raylib-go/raylib"
)

const (
	sliderBorderSize = 4
	sliderWidth      = 200
	sliderHeight     = 30
	sliderTextSize   = 12
	sliderTextOffset = 6
)

type SliderOnChange func(this *Slider)

type Slider struct {
	*base.WithFocus
	Min        int
	Max        int
	Step       int
	Value      int
	borderSize int32
	onChange   SliderOnChange
}

func NewSlider(min, max, step int) *Slider {
	return &Slider{
		WithFocus:  &base.WithFocus{},
		Min:        min,
		Max:        max,
		Step:       step,
		borderSize: 4,
	}
}

func (slider *Slider) WithOnChange(callback SliderOnChange) *Slider {
	slider.onChange = callback
	return slider
}

func (slider Slider) Size() core.Vec2i {
	w := sliderWidth + (sliderBorderSize * 2)
	return core.Vec2i{
		X: w + sliderTextOffset + (sliderTextSize * len(slider.ValueText())),
		Y: sliderHeight + (sliderBorderSize * 2),
	}
}

func (slider *Slider) HandleInput() {
	if input.KeyPressedWithRepeat(rl.KeyLeft) {
		slider.Decrement()
	} else if input.KeyPressedWithRepeat(rl.KeyRight) {
		slider.Increment()
	}
}

func (slider *Slider) SetValue(value int) {
	if value != slider.Value {
		slider.Value = value
		slider.onChange(slider)
	}
}

func (slider *Slider) Increment() {
	slider.SetValue(min(slider.Max, slider.Value+slider.Step))
}

func (slider *Slider) Decrement() {
	slider.SetValue(max(slider.Min, slider.Value-slider.Step))
}

func (slider Slider) Percent() float32 {
	return float32(slider.Min+slider.Value) / float32(slider.Max)
}

func (slider Slider) drawTrack(rect rl.RectangleInt32) {
	spacing := int32(2)
	num_marks := int32(10)
	mark_width := float32(rect.Width-((num_marks+1)*spacing)) / float32(num_marks)

	markRect := rl.Rectangle{
		X:      float32(rect.X + spacing),
		Y:      float32(rect.Y + spacing),
		Width:  mark_width,
		Height: float32(rect.Height - (spacing * 2)),
	}

	for range num_marks {
		rl.DrawRectangleRec(markRect, rl.DarkGray)
		markRect.X += mark_width + float32(spacing)
	}
}

func (slider Slider) drawHandle(x, y, width int32, height int32, col color.RGBA) {
	handleWidth := int32(10)
	x = x + int32(float32(width-handleWidth-2)*slider.Percent())
	rl.DrawRectangle(x, y, handleWidth, height, col)
}

func (slider Slider) ValueText() string {
	return fmt.Sprintf("%d", int(slider.Percent()*100))
}

func (slider Slider) Draw(x, y int32) {
	// rl.DrawRectangle(x, y, int32(slider.Size().X), int32(slider.Size().Y), rl.Green)

	// TODO: use a theme system here so colors are not hardcoded.
	handleColor := rl.White
	if slider.HasFocus() {
		handleColor = rl.Red
	}

	rect := rl.RectangleInt32{
		X:      x + sliderBorderSize,
		Y:      y + sliderBorderSize,
		Width:  sliderWidth,
		Height: sliderHeight,
	}

	render.DrawRectOutlineBorder(rect, slider.borderSize, handleColor)
	slider.drawTrack(rect)
	slider.drawHandle(rect.X+1, rect.Y+1, int32(rect.Width), sliderHeight-2, handleColor)

	textOffset := x + int32(rect.Width) + (sliderBorderSize * 2) + sliderTextOffset

	render.DrawText(textOffset, rect.Y+8, sliderTextSize, slider.ValueText(), rl.White)
}
