package tins2020

import (
	"github.com/veandco/go-sdl2/sdl"
)

type GameControls struct {
	Container

	game    *Game
	dialogs *Dialogs

	menu       ButtonBar
	top        ButtonBar
	flowers    ButtonBar
	otherTools ButtonBar

	pause   *IconButton
	run     *IconButton
	runFast *IconButton

	shovel   *IconButton
	research *IconButton
}

func NewGameControls(game *Game, dialogs *Dialogs) *GameControls {
	return &GameControls{game: game, dialogs: dialogs}
}

func (c *GameControls) createBuyFlowerButton(id string) *BuyFlowerButton {
	flower, _ := c.game.Herbarium.Find(id)
	return NewBuyFlowerButton(
		flower.IconTemplate.Variant(1),
		flower.IconTemplate.Disabled(),
		id,
		flower,
		EmptyEvent(func() {
			c.game.SelectPlantFlowerTool(id)
		}),
	)
}

func (c *GameControls) speedChanged(state interface{}) {
	speed := state.(GameSpeed)
	disable := func(b *IconButton, expected GameSpeed) {
		b.IsDisabled = speed == expected
	}
	disable(c.pause, GameSpeedPaused)
	disable(c.run, GameSpeedNormal)
	disable(c.runFast, GameSpeedFast)
}

func (c *GameControls) toolChanged(state interface{}) {
	tool, _ := state.(Tool)
	var flowerID string
	if tool, ok := tool.(*PlantFlowerTool); ok {
		flowerID = tool.FlowerID
	}
	for _, control := range c.flowers.Buttons {
		button := control.(*BuyFlowerButton)
		button.IsActive = button.FlowerID == flowerID
		button.IsDisabled = !c.game.Herbarium.IsUnlocked(button.FlowerID)
	}
	_, shovel := tool.(*ShovelTool)
	c.shovel.IsActive = shovel
}

func (c *GameControls) Arrange(ctx *Context, bounds Rectangle) {
	c.Bounds = bounds
	c.menu.Arrange(ctx, RectSize(bounds.X, bounds.Y, buttonBarWidth, bounds.H))
	c.top.Arrange(ctx, Rect(bounds.X+bounds.W/2+8, bounds.Y, bounds.Right(), bounds.Y+64))
	c.flowers.Arrange(ctx, RectSize(bounds.Right()-buttonBarWidth, bounds.Y, buttonBarWidth, bounds.H))
	c.otherTools.Arrange(ctx, RectSize(bounds.Right()-buttonBarWidth, bounds.Bottom()-2*buttonBarWidth, buttonBarWidth, 2*buttonBarWidth))
}

func (c *GameControls) Init(ctx *Context) error {
	c.game.SpeedChanged().RegisterItf(c.speedChanged)
	c.game.ToolChanged().RegisterItf(c.toolChanged)
	c.dialogs.DialogOpened().Register(func() { c.game.Pause() })
	c.dialogs.DialogClosed().Register(func() { c.game.Resume() })

	c.flowers.Background = MustHexColor("#356dad")
	c.flowers.ButtonLength = 64

	for _, id := range c.game.Herbarium.Flowers() {
		c.flowers.Buttons = append(c.flowers.Buttons, c.createBuyFlowerButton(id))
	}

	c.top.Orientation = OrientationHorizontal
	c.pause = NewIconButtonConfig("control-pause", EmptyEvent(func() {
		c.game.Pause()
	}), func(b *IconButton) {
		b.IconDisabled = "control-pause-disabled"
	})
	c.run = NewIconButtonConfig("control-run", EmptyEvent(func() {
		c.game.Run()
	}), func(b *IconButton) {
		b.IconDisabled = "control-run-disabled"
	})
	c.runFast = NewIconButtonConfig("control-run-fast", EmptyEvent(func() {
		c.game.RunFast()
	}), func(b *IconButton) {
		b.IconDisabled = "control-run-fast-disabled"
	})
	c.speedChanged(c.game.Speed)
	c.top.Buttons = []Control{c.pause, c.run, c.runFast}

	c.menu.Background = MustHexColor("#356dad")
	c.menu.Buttons = []Control{
		NewIconButton("control-settings", func(*Context) { c.dialogs.ShowSettings() }),
		NewIconButton("control-save", func(*Context) { c.game.Save() }),
		NewIconButton("control-load", func(ctx *Context) {
			c.game.Load()
			for _, b := range c.flowers.Buttons {
				button := b.(*BuyFlowerButton)
				flower, ok := c.game.Herbarium.Find(button.FlowerID)
				if ok {
					button.Update(ctx, flower)
				}
			}
		}),
	}

	c.shovel = NewIconButtonConfig("control-shovel", func(*Context) { c.game.SelectShovel() }, func(b *IconButton) { b.IconHeight = 32 })
	c.research = NewIconButtonConfig("control-research", func(*Context) { c.game.SelectResearch() }, func(b *IconButton) { b.IconHeight = 32 })
	c.otherTools.Buttons = []Control{c.shovel, c.research}

	c.Container.AddChild(&c.menu)
	c.Container.AddChild(&c.top)
	c.Container.AddChild(&c.flowers)
	c.Container.AddChild(&c.otherTools)

	return c.Container.Init(ctx)
}

func (c *GameControls) Handle(ctx *Context, event sdl.Event) bool {
	if c.Container.Handle(ctx, event) {
		return true
	}

	switch e := event.(type) {
	case *sdl.KeyboardEvent:
		if e.Type == sdl.KEYDOWN {
			switch e.Keysym.Sym {
			case sdl.K_SPACE:
				c.game.TogglePause()
			case sdl.K_1:
				c.game.Run()
			case sdl.K_2:
				c.game.RunFast()
			case sdl.K_d:
				c.game.SelectShovel()
			case sdl.K_r:
				c.game.SelectResearch()
			case sdl.K_ESCAPE:
				if c.game.Tool() == nil {
					c.dialogs.ShowIntro()
				} else {
					c.game.CancelTool()
				}
				return true
			case sdl.K_F3:
				c.game.Debug = !c.game.Debug
			}
		}
	}
	return false
}

func (c *GameControls) Render(ctx *Context) {
	topBar := MustHexColor("#0000007f")
	SetDrawColor(ctx.Renderer, topBar)
	ctx.Renderer.FillRect(Rect(c.menu.Bounds.Right(), 0, c.flowers.Bounds.X, 64).SDLPtr())
	ctx.Fonts.Font("balance").RenderCopyAlign(ctx.Renderer, FmtMoney(c.game.Balance), Pt(c.top.Bounds.X-8, 58), MustHexColor("#4AC69A"), TextAlignmentRight)

	c.Container.Render(ctx)
}