package game

import (
	"fmt"
	"image/color"
	"log/slog"
	"openquell/assets"
	"openquell/config"
	"openquell/gameui"
	"openquell/observers"

	"github.com/ebitenui/ebitenui"
	"github.com/ebitenui/ebitenui/widget"

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

type NextlevelScene struct {
	Game     *Game
	Next     SceneName
	Whoami   SceneName
	UseCache bool
	Ui       *ebitenui.UI
	Lost     bool
}

func NewNextlevelScene(game *Game) Scene {
	scene := &NextlevelScene{
		Whoami: Nextlevel,
		Game:   game,
		Next:   Nextlevel,
	}

	scene.SetupUI()

	return scene
}

func (scene *NextlevelScene) GetNext() SceneName {
	return scene.Next
}

func (scene *NextlevelScene) ResetNext() {
	scene.Next = scene.Whoami
}

func (scene *NextlevelScene) SetNext(next SceneName) {
	slog.Debug("select setnext", "next", next)
	scene.Next = next
}

func (scene *NextlevelScene) Clearscreen() bool {
	// both level_scene AND the popup must not clear to get an actual popup
	return false
}

func (scene *NextlevelScene) Update() error {
	scene.Ui.Update()
	return nil
}

func (scene *NextlevelScene) SetLevel(level int) {}

func (scene *NextlevelScene) Draw(screen *ebiten.Image) {
	background := assets.Assets["background-popup-wide"]

	op := &ebiten.DrawImageOptions{}
	op.GeoM.Translate(
		float64((scene.Game.ScreenWidth/2)-(background.Bounds().Dx()/2)),
		float64((scene.Game.ScreenHeight/2)-(background.Bounds().Dy()/2)),
	)

	screen.DrawImage(background, op)

	scene.Ui.Draw(screen)
}

func (scene *NextlevelScene) SetupUI() {
	observer := observers.GetGameObserver(scene.Game.World)
	slog.Debug("levels", "max", observer.MaxLevels, "current", observer.CurrentLevel)
	if observer.MaxLevels == observer.CurrentLevel+1 && !observer.Lost {
		scene.SetupUILast()
	} else {
		scene.SetupUIRetry()
	}

}

func (scene *NextlevelScene) SetupUILast() {
	blue := color.RGBA{0, 255, 128, 255}
	observer := observers.GetGameObserver(scene.Game.World)

	rowContainer := gameui.NewRowContainer(false)
	label1text := "Last level, congratulations!"
	label2text := fmt.Sprintf("Your final score: %d", observer.GetScore())

	buttonMenu := gameui.NewMenuButton("Menu", *assets.FontRenderer.FontNormal,
		func(args *widget.ButtonClickedEventArgs) {
			scene.SetNext(Menu)
		})

	label1 := widget.NewText(
		widget.TextOpts.Text(label1text, *assets.FontRenderer.FontNormal, blue),
		widget.TextOpts.Position(widget.TextPositionCenter, widget.TextPositionCenter),
	)

	label2 := widget.NewText(
		widget.TextOpts.Text(label2text, *assets.FontRenderer.FontNormal, blue),
		widget.TextOpts.Position(widget.TextPositionCenter, widget.TextPositionCenter),
	)

	rowContainer.AddChild(label1)
	rowContainer.AddChild(label2)
	rowContainer.AddChild(buttonMenu)

	scene.Ui = &ebitenui.UI{
		Container: rowContainer.Container(),
	}
}

func (scene *NextlevelScene) SetupUIRetry() {
	observer := observers.GetGameObserver(scene.Game.World)
	buttonNext := &widget.Button{}

	rowContainer := gameui.NewRowContainer(false)
	labeltext := fmt.Sprintf("Great! (Score: %d)", observer.GetLevelScore())
	islast := observer.MaxLevels == observer.CurrentLevel+1

	switch observer.Lost {
	case true:
		labeltext = "Too bad!"
	}

	buttonRetry := gameui.NewMenuButton("Retry", *assets.FontRenderer.FontNormal,
		func(args *widget.ButtonClickedEventArgs) {
			scene.SetNext(Play)
			observer.Retry = true
		})

	if !islast {
		buttonNext = gameui.NewMenuButton("Next Level", *assets.FontRenderer.FontNormal,
			func(args *widget.ButtonClickedEventArgs) {
				scene.SetNext(Play)
				observer.Retry = false
			})
	}

	buttonAbort := gameui.NewMenuButton("Abort", *assets.FontRenderer.FontNormal,
		func(args *widget.ButtonClickedEventArgs) {
			scene.SetNext(Menu)
		})

	label := widget.NewText(
		widget.TextOpts.Text(labeltext, *assets.FontRenderer.FontNormal, config.FontColorFG),
		widget.TextOpts.Position(widget.TextPositionCenter, widget.TextPositionCenter),
	)

	rowContainer.AddChild(label)
	if !islast {
		rowContainer.AddChild(buttonNext)
	}
	rowContainer.AddChild(buttonRetry)
	rowContainer.AddChild(buttonAbort)

	scene.Ui = &ebitenui.UI{
		Container: rowContainer.Container(),
	}
}
