package main

import (
	"fmt"
	"strings"

	"github.com/awesome-gocui/gocui"
	log "go.wit.com/log"
	"go.wit.com/toolkits/tree"
	"go.wit.com/widget"
)

// dropdowns don't exist so this is an attempt to pretend they exist
// by having a fake window view in gocui that appears with the dropdown
// items. by detecting where the user clicks, we should be
// able to set the text of the button to that value (and
// rezise it.

// the thing is this is so damned complicated because it
// is very hard to debug this. thanks to the floating on
// screen debugging output I might be able to figure it
// it out now. maybe. notsure.

func makeDropdownView(ddItems string) *guiWidget {
	newNode := addDropdown()
	tk := newNode.TK.(*guiWidget)
	tk.labelN = ddItems
	tk.SetText(ddItems)
	tk.gocuiSize.w0 = 100
	tk.gocuiSize.w1 = 120
	tk.gocuiSize.h0 = 15
	tk.gocuiSize.h1 = 18
	tk.v, _ = me.baseGui.SetView("ddview",
		tk.gocuiSize.w0,
		tk.gocuiSize.h0,
		tk.gocuiSize.w1,
		tk.gocuiSize.h1, 0)
	if tk.v == nil {
		return tk
	}
	tk.v.Wrap = true
	tk.v.Frame = true
	tk.v.Clear()
	fmt.Fprint(tk.v, ddItems)
	tk.Show()
	return tk
}

func addDropdown() *tree.Node {
	n := new(tree.Node)
	n.WidgetType = widget.Flag
	n.WidgetId = 2222
	n.ParentId = 0

	// store the internal toolkit information
	tk := new(guiWidget)
	tk.frame = true
	tk.labelN = "DropBox text"

	tk.node = n
	// copy the data from the action message
	tk.node.State.Label = "DropBox"

	// set the name used by gocui to the id
	tk.cuiName = "-1 dropbox"

	tk.color = &colorFlag

	// add this new widget on the binary tree
	tk.parent = me.treeRoot.TK.(*guiWidget)
	if tk.parent == nil {
		panic("addDropdown() didn't get treeRoot guiWidget")
	} else {
		tk.parent.children = append(tk.parent.children, tk)
	}

	n.TK = tk
	return n
}

func (tk *guiWidget) showDropdown() {
	var ddItems string
	// todo: fix this after switching to protobuf
	// var items []string
	// items = tk.node.State.Strings
	//for i, s := range items {
	for i, s := range tk.node.Strings() {
		log.Log(GOCUI, "showDropdown()", tk.String(), i, s)
		ddItems += s + "\n"
	}

	log.Log(GOCUI, "new dropdown items should be set to:", ddItems)
	sizeW, sizeH := tk.Size()
	log.Log(GOCUI, "showDropdown() size W,H=", sizeW, sizeH)
	startW, startH := tk.Position()
	log.Log(GOCUI, "showDropdown() location W,H=", startW, startH)
	me.dropdownV.MoveToOffset(startW+3, startH+2)
	me.dropdownV.labelN = ddItems
	me.dropdownV.Show()
}

func hideDDview() error {
	w, h := me.baseGui.MousePosition()
	log.Log(GOCUI, "hide dropdown menu() view msgMouseDown (w,h) =", w, h)
	if me.dropdownV == nil {
		return gocui.ErrUnknownView
	}
	if me.dropdownV.v == nil {
		return gocui.ErrUnknownView
	}
	me.dropdownV.SetVisible(false)
	return nil
}

func showDDview() error {
	w, h := me.baseGui.MousePosition()
	log.Log(GOCUI, "show dropdown menu() view msgMouseDown (w,h) =", w, h)
	if me.dropdownV == nil {
		return gocui.ErrUnknownView
	}
	if me.dropdownV.v == nil {
		return gocui.ErrUnknownView
	}
	me.dropdownV.SetVisible(true)
	return nil
}

// if there is a drop down view active, treat it like a dialog box and close it
func (w *guiWidget) dropdownClicked(mouseW, mouseH int) string {
	w.Hide()

	startW, startH := w.Position()
	log.Log(GOCUI, "dropdownClicked() start (w,h) =", startW, startH)
	log.Log(GOCUI, "dropdownClicked() at    (w,h) =", mouseW, mouseH)

	itemNumber := mouseH - startH
	items := strings.Split(w.labelN, "\n")
	log.Log(GOCUI, "dropdownClicked() look for item", itemNumber, "len(items) =", len(items))
	if itemNumber < 1 {
		return ""
	}

	if len(items) >= itemNumber {
		log.Log(GOCUI, "dropdownClicked() found", items[itemNumber-1])
		if items[itemNumber-1] != "" {
			if me.dropdownW != nil {
				log.Log(GOCUI, "dropdownClicked() send event for", me.dropdownW.cuiName, me.dropdownW.WidgetType)
				me.dropdownW.SetText(items[itemNumber-1])
				me.dropdownW.node.SetCurrentS(items[itemNumber-1])
				me.myTree.SendUserEvent(me.dropdownW.node)
			}
		}
		return items[itemNumber-1]
	}
	return ""
}

var dtoggle bool    // temporarily tracking show & hide
var doffset int = 5 // how many spaces over the dropdown menu should be from the mouse

func dropdownUnclicked(mouseW, mouseH int) {
	var d *guiWidget

	// log.Log(GOCUI, "dropdownUnclicked() mouseup: got inside me.dropdown handler? wxh =", mouseW, mouseH)
	if me.dropdownV == nil {
		log.Log(GOCUI, "mouseUp() dropdownV = nil. you don't have a fake dropdown window to make visible", mouseW, mouseH)
		return
	}
	// log.Log(GOCUI, fmt.Sprintf("dropdownUnclicked at apparently (w=%d h=%d)", mouseW, mouseH))
	// log.Log(GOCUI, "dropdownUnclicked() find out what the string is here", mouseW, mouseH, tk.gocuiSize.h1)

	// examine everything under X & Y on the screen)
	for i, w := range findByXY(mouseW, mouseH) {
		log.Log(GOCUI, "dropdownUnclicked()", i, w.WidgetType)
		if w.WidgetType == widget.Dropdown {
			d = w
			break
		}
	}
	if d == nil {
		log.Log(GOCUI, fmt.Sprintf("dropdownUnclicked() there was no dropdown widget at (w=%d h=%d)", mouseW, mouseH))
		return
	}
	log.Log(GOCUI, "dropdownUnclicked()", d.node.Strings(), "end. now try to enable me.dropdownV")
	dtext := strings.Join(d.node.Strings(), "\n")
	tk := me.dropdownV
	if dtoggle {
		log.Log(GOCUI, "dropdownUnclicked() set visible=false")
		tk.Hide()
		dtoggle = false
		tk.SetText("goodbye")
	} else {
		log.Log(GOCUI, "dropdownUnclicked() set visible=true")
		tk.MoveToOffset(mouseW+doffset, mouseH)
		tk.SetText(dtext)
		tk.Show()
		dtoggle = true
	}
}