package main

import (
	"errors"

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

func (w *guiWidget) doWidgetClick() {
	switch w.WidgetType {
	/*
		case widget.Root:
			// THIS IS THE BEGINING OF THE LAYOUT
			log.Log(GOCUI, "doWidgetClick()", w.String())
			wRoot := me.treeRoot.TK.(*guiWidget)
			wRoot.redoWindows(0, 0)
		case widget.Flag:
			log.Log(GOCUI, "doWidgetClick() FLAG widget name =", w.String())
			log.Log(GOCUI, "doWidgetClick() if this is the dropdown menu, handle it here?")
	*/
	case widget.Window:
		log.Log(GOCUI, "doWidgetClick() START on window", w.String())
		// if the user clicked on the current window, do nothing
		/* Ignore this for now and redraw the window anyway
		if me.currentWindow == w {
			if !w.active {
				return
			}
		}
		*/

		// if there is a current window, hide it
		if me.currentWindow != nil {
			me.currentWindow.setColor(&colorWindow)
			me.currentWindow.hideWidgets()
			me.currentWindow.isCurrent = false
		}

		// now set this window as the current window
		me.currentWindow = w
		me.currentWindow.isCurrent = true

		// draw the current window
		log.Log(GOCUI, "doWidgetClick() set currentWindow to", w.String())
		w.setColor(&colorActiveW)
		w.DrawAt(3, 2)
		w.placeWidgets(3, 2) // compute the sizes & places for each widget
		w.active = false
		w.showWidgets()
		/*
			hideFake()
			showDebug = true
		*/
	case widget.Group:
		if w.active {
			w.active = false
			w.placeWidgets(w.startW, w.startH)
			w.showWidgets()
		} else {
			w.active = true
			for _, child := range w.children {
				child.hideWidgets()
			}
		}
		// w.dumpTree("click end")
	case widget.Checkbox:
		if w.node.State.Checked {
			log.Log(WARN, "checkbox is being set to false")
			w.node.State.Checked = false
			w.setCheckbox()
		} else {
			log.Log(WARN, "checkbox is being set to true")
			w.node.State.Checked = true
			w.setCheckbox()
		}
		me.myTree.SendUserEvent(w.node)
	case widget.Grid:
		newR := w.realGocuiSize()

		// w,h := n.logicalSize()
		// w := newR.w1 - newR.w0
		// h := newR.h1 - newR.h0

		w.placeGrid(newR.w0, newR.h0)
		w.showWidgets()
	case widget.Box:
		// w.showWidgetPlacement(logNow, "drawTree()")
		if w.node.State.Direction == widget.Horizontal {
			log.Log(GOCUI, "BOX IS HORIZONTAL", w.String())
		} else {
			log.Log(GOCUI, "BOX IS VERTICAL", w.String())
		}
		w.placeWidgets(w.startW, w.startH)
		w.toggleTree()
	case widget.Button:
		// doUserEvent(n)
		me.myTree.SendFromUser(w.node)
	case widget.Combobox:
		log.Log(GOCUI, "do the combobox here")
		w.showDropdown()
		me.dropdownW = w
	case widget.Dropdown:
		log.Log(GOCUI, "do the dropdown here")
		w.showDropdown()
		me.dropdownW = w
	default:
	}
}

func click(g *gocui.Gui, v *gocui.View) error {
	mouseW, mouseH := me.baseGui.MousePosition()

	log.Log(GOCUI, "click() START gocui name:", v.Name())
	w := findUnderMouse()

	// if the dropdown view is visable, process it no matter what
	if me.dropdownV.Visible() {
		me.dropdownV.dropdownClicked(mouseW, mouseH)
	}
	if w == me.dropdownV {
		return nil
	}

	if w == nil {
		log.Error(errors.New("click() could not find widget for view =" + v.Name()))
	} else {
		log.Log(GOCUI, "click() Found widget =", w.node.WidgetId, w.String(), ",", w.labelN)
		w.doWidgetClick()
	}

	rootTK := me.treeRoot.TK.(*guiWidget)
	realTK := rootTK.findWidgetByView(v)
	if realTK == nil {
		log.Error(errors.New("toolkit click() out of reality with gocui. v.Name() not in binary tree " + v.Name()))
		log.Log(GOCUI, "click() END FAILURE ON gocui v.Name =", v.Name())
		// return nil // otherwise gocui exits
	}

	// double check the widget view really still exists
	nameTK := rootTK.findWidgetByName(v.Name())
	if nameTK == nil {
		log.Error(errors.New("toolkit click() out of reality with gocui. v.Name() not in binary tree " + v.Name()))
		return nil
	}
	if nameTK.v == nil {
		log.Log(GOCUI, "click() maybe this widget has had it's view distroyed?", nameTK.cuiName, nameTK.WidgetType)
		log.Log(GOCUI, "yep. it's gone now")
		return nil
	}

	// SetCurrentView dies if it's sent an non-existent view
	if _, err := g.SetCurrentView(v.Name()); err != nil {
		log.Log(GOCUI, "click() END v.Name =", v.Name(), "err =", err)
		// return err // return causes gocui.MainLoop() to exit. Do we ever want that to happen here?
		return nil
	}

	log.Log(GOCUI, "click() END gocui name:", v.Name())
	return nil
}

func findUnderMouse() *guiWidget {
	var widgets []*guiWidget
	var f func(w *guiWidget)
	w, h := me.baseGui.MousePosition()

	// find buttons that are below where the mouse button click
	f = func(widget *guiWidget) {
		// ignore widgets that are not visible
		if widget.Visible() {
			if (widget.gocuiSize.w0 <= w) && (w <= widget.gocuiSize.w1) &&
				(widget.gocuiSize.h0 <= h) && (h <= widget.gocuiSize.h1) {
				widgets = append(widgets, widget)
			}
		}

		for _, child := range widget.children {
			f(child)
		}
	}
	rootW := me.treeRoot.TK.(*guiWidget)
	f(rootW)

	var found *guiWidget
	// widgets has everything that matches
	for _, w := range widgets {
		// prioritize window buttons. This means if some code covers
		// up the window widgets, then it will ignore everything else
		// and allow the user (hopefully) to redraw or switch windows
		// TODO: display the window widgets on top
		if w.WidgetType == widget.Window {
			return w
		}
		// w.showWidgetPlacement("findUnderMouse() FOUND")
		found = w
	}
	return found
}

// find the widget under the mouse click
func ctrlDown(g *gocui.Gui, v *gocui.View) error {
	var found *guiWidget
	// var widgets []*node
	// var f func (n *node)
	found = findUnderMouse()
	if me.ctrlDown == nil {
		setupCtrlDownWidget()

		var tk *guiWidget
		tk = me.ctrlDown.TK.(*guiWidget)
		tk.labelN = found.String()
		tk.cuiName = "ctrlDown"
		// me.ctrlDown.parent = me.rootNode
	}
	var tk *guiWidget
	tk = me.ctrlDown.TK.(*guiWidget)
	if found == nil {
		found = me.treeRoot.TK.(*guiWidget)
	}
	tk.labelN = found.String()
	newR := found.realGocuiSize()
	tk.gocuiSize.w0 = newR.w0
	tk.gocuiSize.h0 = newR.h0
	tk.gocuiSize.w1 = newR.w1
	tk.gocuiSize.h1 = newR.h1
	return nil
}