package screens

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

type InventoryScreen struct {
	*MenuScreen
	who ecs.Entity

	cursor   int
	offset   int
	pageSize int
	selected []int

	prepared preparedList
}

type displayItem struct {
	Entity   ecs.Entity
	Name     string
	Index    string
	Selected bool
}

type preparedList []displayItem

func (p *preparedList) Prepare(is *InventoryScreen) {

	//fixme add item class sorting

	bp := items.Controller.GetComponent(is.who, ecs.BackpackComponent).(items.Backpack)
	is.prepared = make([]displayItem, len(bp.GetItems()))
	//prepare item list
	for i, ent := range bp.GetItems() {
		namec := items.Controller.GetComponent(ent, ecs.Named{}.Type()).(ecs.Named)
		is.prepared[i] = displayItem{
			Entity: ent,
			Name:   namec.Name,
			Index:  string(runeIndex[i]),
		}
	}
}

func (is *InventoryScreen) MakeInverntory(who ecs.Entity) *InventoryScreen {
	is.drawFunc = is.InventoryRender
	is.inputFunc = is.HandleInput
	is.who = who
	return is
}

func (is *InventoryScreen) Enter() {
	is.redraw = true
	is.offset = 0
	is.cursor = 0

	is.prepared = preparedList{}
	is.prepared.Prepare(is)
}

//fixme key names to action constants!
//fixme unify scrolling controls!
func (is *InventoryScreen) HandleInput(input string) {
	if strings.Contains(string(runeIndex), strings.Replace(input, "Shift+", "", -1)) {
		if strings.Contains("Shift+", input) {
			input = strings.ToUpper(input)
		}
		for i, _ := range is.prepared {
			if is.prepared[i].Index == input {
				is.prepared[i].Selected = !is.prepared[i].Selected
			}
		}
		return
	}
	switch input {
	case "Up", "k":
		is.cursor = is.cursor - 1
		if is.cursor < 0 {
			is.cursor = 0
		}
		if is.cursor < is.offset {
			is.offset = is.offset - 1
			if is.offset < 0 {
				is.offset = 0
			}
		}
		break
	case "Down", "j":
		is.cursor = is.cursor + 1
		if is.cursor >= len(is.prepared) {
			is.cursor = len(is.prepared) - 1
		}
		if is.cursor > is.offset {
			is.offset = is.offset + 1
			if is.offset*is.pageSize > len(is.prepared) {
				is.offset = len(is.prepared) / is.pageSize
			}
		}
		break
	case "Left":
		is.prepared[is.cursor].Selected = false
		break
	case "Right":
		is.prepared[is.cursor].Selected = true
		break
	case "PageUp":
		is.offset = is.offset - 1
		if is.offset < 0 {
			is.offset = 0
		}
		break
	case "PageDown":
		is.offset = is.offset + 1
		if is.offset > len(is.prepared)-1 {
			is.offset = len(is.prepared) - 1
		}
		break
	case "enter":
		//show actions menu for item under cursor
		//fixme implement
		break;
	case "Escape":
		fallthrough
	case "Space":
		is.scm.SetScreen(is.scm.PreviousScreen)
		break
	}
}

func (is *InventoryScreen) InventoryRender() {
	menuLayer := is.mw.GetLayer("menu")
	menuLayer.ClearRect(is.Rect)
	bgLayer := is.mw.GetLayer("menubg")
	bgLayer.ClearRect(is.Rect)
	bgLayer.WithColor(is.bgColor).NewWindow(is.Rect).Splash()
	menuLayer.WithColor(is.fgColor).NewWindow(is.Rect).DoubleBordered(is.title)
	menuLayer.Print(is.X+(is.W/2)-7, is.Y+is.H-1, "╡"+"[color=green]Space[/color] to close"+"╞")
	footerHeight := 0
	if is.footer != "" {
		_, footerHeight = menuLayer.PrintInside(is.Rect, is.footer, 9)
		footerHeight = footerHeight + 2
	}
	_, headerHeight := menuLayer.PrintInside(is.Rect, is.header, blt.TK_ALIGN_LEFT)
	itemField := types.Rect{
        X: is.X,
        Y: is.Y + headerHeight + 1,
        W: is.W,
        H: is.H - headerHeight - footerHeight,
    }
	_ = itemField
	is.pageSize = itemField.H - 2

	if (len(is.prepared) > 0) {

		for i := is.offset; i < itemField.H; i++ {
			if i < len(is.prepared) {
				selectedColor := "white"
				selectedDash := "-"
				if is.prepared[i].Selected {
					selectedColor = "green"
					selectedDash = "+"
				}
				if is.cursor == i {
					menuLayer.WithColor("yellow")
				} else {
					menuLayer.WithColor("white")
				}
				menuStr := fmt.Sprintf("[color=%s]%s[/color] %s %s", selectedColor, is.prepared[i].Index, selectedDash, is.prepared[i].Name)
				if len(menuStr) > itemField.W - 2 {
					menuStr = menuStr[0:itemField.W - 2]
				}
				menuLayer.PutStringInto(itemField,i,menuStr,1)
			}
		}
	}
	if is.cursor < len(is.prepared) {
		is.drawScrollBar(menuLayer, itemField)
	}
}

//func (ms *InventoryScreen) UseEcs() bool {return true}
//func (ms *InventoryScreen) Enter()       {}

//func (ms *InventoryScreen) Exit()   {}
//func (ms *InventoryScreen) Render() {}
