package screens

import (
	"fmt"
	"lab.zaar.be/thefish/alchemyst-go/engine/types"
	"lab.zaar.be/thefish/alchemyst-go/ui/mainwindow"
	blt "lab.zaar.be/thefish/bearlibterminal"
	"strings"
)

const runeIndex = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

type MenuScreen struct {
	types.Rect

	mw           *mainwindow.MainWindow
	scm          *types.ScreenManager
	renderParent bool

	items  []interface{}
	offset int

	drawFunc  func()
	inputFunc func(string)

	title   string
	header  string
	footer  string
	redraw  bool
	bgColor string
	fgColor string
}

func NewMenuScreen(mw *mainwindow.MainWindow, scm *types.ScreenManager, title, header, footer string, rect types.Rect, renderParent bool) *MenuScreen {
	return &MenuScreen{
		title:        title,
		header:       header,
		footer:       footer,
		Rect:         rect,
		mw:           mw,
		scm:          scm,
		renderParent: renderParent,
	}
}

func (ms *MenuScreen) MakeList() *MenuScreen {
	ms.drawFunc = ms.ListRender
	ms.inputFunc = ms.ListHandleInput
	return ms
}

func (ms *MenuScreen) SetBgColor(color string) *MenuScreen {
	ms.bgColor = color
	return ms
}

func (ms *MenuScreen) SetFgColor(color string) *MenuScreen {
	ms.fgColor = color
	return ms
}

//fixme!!

func (ms *MenuScreen) SetItems(items []interface{}) *MenuScreen {
	ms.items = items
	return ms
}

func (ms *MenuScreen) UseEcs() bool { return false }

func (ms *MenuScreen) Enter() {
	ms.redraw = true
	ms.offset = 0
}

func (ms *MenuScreen) HandleInput(input string) {
	ms.inputFunc(input)
}

func (ms *MenuScreen) Exit() {
	menuLayer := ms.mw.GetLayer("menu")
	menuLayer.ClearRect(ms.Rect)
	bgLayer := ms.mw.GetLayer("menubg")
	bgLayer.ClearRect(ms.Rect)
}

func (ms *MenuScreen) Render() {
	if ms.renderParent {
		ms.scm.PreviousScreen.Render()
	}
	if (ms.redraw || ms.renderParent) {
		ms.redraw = false
		ms.drawFunc()
	}
}

func (ms *MenuScreen) ListHandleInput(input string) {
	switch input {
	case "Up":
		ms.offset = ms.offset - 1
		if ms.offset < 0 {
			ms.offset = 0
		}
		break
	case "Down":
		ms.offset = ms.offset + 1
		if ms.offset > len(ms.items)-1 {
			ms.offset = len(ms.items) - 1
		}
		break
	case "Escape":
		fallthrough
	case "Space":
		ms.scm.SetScreen(ms.scm.PreviousScreen)
		break
	}
}

func (ms *MenuScreen) ListRender() {
	menuLayer := ms.mw.GetLayer("menu")
	menuLayer.ClearRect(ms.Rect)
	bgLayer := ms.mw.GetLayer("menubg")
	bgLayer.ClearRect(ms.Rect)
	bgLayer.WithColor(ms.bgColor).NewWindow(ms.Rect).Splash()
	menuLayer.WithColor(ms.fgColor).NewWindow(ms.Rect).DoubleBordered(ms.title)
	menuLayer.Print(ms.X+(ms.W/2)-7, ms.Y+ms.H-1, "╡"+"[color=green]Space[/color] to close"+"╞")
	footerHeight := 0
	if ms.footer != "" {
		_, footerHeight = menuLayer.PrintInside(ms.Rect, ms.footer, 9)
		footerHeight = footerHeight + 2
	}
	_, headerHeight := menuLayer.PrintInside(ms.Rect, ms.header, blt.TK_ALIGN_LEFT)
	itemField := types.Rect{ms.X, ms.Y + headerHeight + 1, ms.W, ms.H - headerHeight - footerHeight}
	_ = itemField
	var ilw, ilh int
	if (len(ms.items) > 0) {
		//fixme itemfield object, scroller, inputhandler, current selected item
		menuItems := make([]string, 0)
		for i := ms.offset; i < len(ms.items); i++ {
			if string(ms.items[i].(string)) != "" {
				menuItems = append(menuItems, ms.items[i].(string))
			}
		}
		ilw, ilh = menuLayer.PrintInside(itemField, strings.Join(menuItems, "\n"), blt.TK_ALIGN_LEFT)
	}
	if ilh < len(ms.items) {
		ms.drawScrollBar(menuLayer, itemField)
	}
	if ilw > itemField.W-4 {
		fmt.Printf("Excess width of item names found! Need h-scroll of certain names")
	}
}

func (ms *MenuScreen) drawScrollBar(menuLayer *mainwindow.Layer, itemField types.Rect) {
	scrollbarBg := types.NewRect(itemField.X+itemField.W-2, itemField.Y + 1, 1, itemField.H - 4)
	menuLayer.WithColor("#77000000").NewWindow(scrollbarBg).Splash()
	//tick
	menuLayer.WithColor(ms.fgColor).Put(
		scrollbarBg.X,
		scrollbarBg.Y + int(float64(ms.offset) / float64(len(ms.items)) * float64(scrollbarBg.H)),
		"⏹",
	)
	menuLayer.WithColor(ms.fgColor).Put(itemField.X+itemField.W-2, itemField.Y+scrollbarBg.H + 1, "↓")
	menuLayer.WithColor(ms.fgColor).Put(itemField.X+itemField.W-2, itemField.Y, "↑")

}