package windows

import (
	"git.kirsle.net/SketchyMaze/doodle/pkg/balance"
	"git.kirsle.net/SketchyMaze/doodle/pkg/drawtool"
	"git.kirsle.net/SketchyMaze/doodle/pkg/level"
	"git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
	"git.kirsle.net/SketchyMaze/doodle/pkg/uix"
	"git.kirsle.net/go/render"
	"git.kirsle.net/go/render/event"
	"git.kirsle.net/go/ui"
)

// PiP window.
type PiP struct {
	// Settings passed in by doodle
	Supervisor *ui.Supervisor
	Engine     render.Engine
	Level      *level.Level
	Event      *event.State
	Tool       *drawtool.Tool
	BrushSize  *int

	// Or sensible defaults:
	Width  int
	Height int

	OnCancel func()
}

// MakePiPWindow initializes a license window for any scene.
// The window width/height are the actual SDL2 window dimensions.
func MakePiPWindow(windowWidth, windowHeight int, cfg PiP) *ui.Window {
	win := NewPiPWindow(cfg)
	win.Compute(cfg.Engine)
	win.Supervise(cfg.Supervisor)

	// Center the window.
	size := win.Size()
	win.MoveTo(render.Point{
		X: (windowWidth / 2) - (size.W / 2),
		Y: (windowHeight / 2) - (size.H / 2),
	})

	return win
}

// NewPiPWindow initializes the window.
func NewPiPWindow(cfg PiP) *ui.Window {
	var (
		windowWidth  = 340
		windowHeight = 300
	)

	if cfg.Width+cfg.Height > 0 {
		windowWidth = cfg.Width
		windowHeight = cfg.Height
	}

	var (
		canvasWidth  = windowWidth - 8
		canvasHeight = windowHeight - 4 - 48 // for the titlebar?
	)

	window := ui.NewWindow("Viewport")
	window.SetButtons(ui.CloseButton)
	window.Configure(ui.Config{
		Width:  windowWidth,
		Height: windowHeight,
	})

	canvas := uix.NewCanvas(128, true)
	canvas.Name = "Viewport (WIP)"
	canvas.LoadLevel(cfg.Level)
	canvas.InstallActors(cfg.Level.Actors)
	canvas.Scrollable = true
	canvas.Editable = true
	canvas.Resize(render.NewRect(canvasWidth, canvasHeight))

	// If we have tool bindings to edit in PiP window
	var (
		editable bool
		curTool  drawtool.Tool
		curThicc int
	)
	if cfg.Tool != nil && cfg.BrushSize != nil {
		editable = true
		curTool = *cfg.Tool
		curThicc = *cfg.BrushSize
		canvas.Tool = curTool
	}

	// NOTE: my UI toolkit calls this every tick, if this is "fixed"
	// in the future make one that does.
	window.Handle(ui.MouseMove, func(ed ui.EventData) error {
		canvas.Loop(cfg.Event)

		// Did we have tool bindings for an editable PiP?
		if editable {
			// Check if bound values have modified.
			if *cfg.Tool != curTool {
				curTool = *cfg.Tool
				canvas.Tool = curTool
			}
			if *cfg.BrushSize != curThicc {
				curThicc = *cfg.BrushSize
				canvas.BrushSize = curThicc
			}
		}

		return nil
	})

	window.Pack(canvas, ui.Pack{
		Side:  ui.N,
		FillX: true,
	})

	/////////////
	// Buttons at bottom of window

	bottomFrame := ui.NewFrame("Button Frame")
	window.Pack(bottomFrame, ui.Pack{
		Side:  ui.N,
		FillX: true,
		PadY:  4,
	})

	frame := ui.NewFrame("Button frame")
	buttons := []struct {
		label   string
		tooltip string
		f       func()
	}{
		{"Smaller", "Shrink this viewport window by 20%", func() {
			// Make a smaller version of the same window, and close.
			cfg.Width = int(float64(windowWidth) * 0.8)
			cfg.Height = int(float64(windowHeight) * 0.8)
			pip := MakePiPWindow(cfg.Width, cfg.Height, cfg)
			pip.MoveTo(window.Point())
			window.Close()
			pip.Show()
		}},
		{"Larger", "Grow this viewport window by 20%", func() {
			// Make a smaller version of the same window, and close.
			cfg.Width = int(float64(windowWidth) * 1.2)
			cfg.Height = int(float64(windowHeight) * 1.2)
			pip := MakePiPWindow(cfg.Width, cfg.Height, cfg)
			pip.MoveTo(window.Point())
			window.Close()
			pip.Show()
		}},
		{"Refresh", "Update the state of doodads placed in this level", func() {
			canvas.ClearActors()
			canvas.InstallActors(cfg.Level.Actors)
		}},
		{"Rename", "Give this viewport window a custom name", func() {
			shmem.Prompt("Give this viewport a name: ", func(answer string) {
				if answer == "" {
					return
				}
				window.Title = answer
			})
		}},
		{"???", "Load a different drawing (experimental!)", func() {
			shmem.Prompt("Filename to open: ", func(answer string) {
				if answer == "" {
					return
				}

				if lvl, err := level.LoadFile(answer); err == nil {
					canvas.ClearActors()
					canvas.LoadLevel(lvl)
					canvas.InstallActors(lvl.Actors)
				} else {
					shmem.Flash(err.Error())
				}
			})
		}},
	}
	for i, button := range buttons {
		// Start axing buttons if window size is too small.
		if windowWidth < 150 && i > 1 {
			break
		} else if windowWidth < 250 && i > 2 {
			break
		}

		button := button

		btn := ui.NewButton(button.label, ui.NewLabel(ui.Label{
			Text: button.label,
			Font: balance.SmallFont,
		}))

		btn.Handle(ui.Click, func(ed ui.EventData) error {
			button.f()
			return nil
		})

		btn.Compute(cfg.Engine)
		cfg.Supervisor.Add(btn)

		ui.NewTooltip(btn, ui.Tooltip{
			Text: button.tooltip,
			Edge: ui.Top,
		})

		frame.Pack(btn, ui.Pack{
			Side:   ui.W,
			PadX:   1,
			Expand: true,
			Fill:   true,
		})
	}

	bottomFrame.Pack(frame, ui.Pack{
		Side: ui.N,
		PadX: 8,
		PadY: 0,
	})

	return window
}
