// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
// Use of this source code is governed by the GPL 3.0

package main

import (
	"fmt"
	"strings"

	log "go.wit.com/log"
	"go.wit.com/toolkits/tree"
	"go.wit.com/widget"
)

func (tk *guiWidget) setTitle(s string) {
	if tk.node.WidgetType != widget.Window {
		return
	}
	if tk.v == nil {
		return
	}
	tk.setColorWindowTitleActive()
	rect := tk.gocuiSize
	rect.w1 = rect.w0 + tk.full.Width() + 1
	// rect.h1 = rect.h0 + 1
	me.baseGui.SetView(tk.v.Name(), rect.w0-1, rect.h0, rect.w1+1, rect.h1, 0)
	tk.v.Clear()
	f := "  %-" + fmt.Sprintf("%d", tk.full.Width()-3) + "s %s"
	// tmp := tk.node.GetLabel() + " " + tk.v.Name() + " " + f
	tmp := tk.node.GetLabel()
	labelN := fmt.Sprintf(f, tmp, "X")
	tk.v.WriteString(labelN)
}

func (tk *guiWidget) redrawWindow(w int, h int) {
	if tk.node.WidgetType != widget.Window {
		return
	}
	// tk.dumpWidget(fmt.Sprintf("redrawWindow(%d,%d)", w, h))
	if tk.full.Height() > 40 {
		tk.window.dense = true
	}
	// pin the window to (w,h)
	tk.gocuiSize.w0 = w
	tk.gocuiSize.h0 = h
	tk.gocuiSize.w1 = w + len(tk.node.GetLabel())
	tk.labelN = tk.node.GetLabel() // could set XX here also but don't have final size of window yet
	tk.force.w0 = w
	tk.force.w1 = w
	tk.force.h0 = h
	tk.force.h1 = h

	tk.setFullSize() // might make the green box the right size

	tk.frame = false
	tk.hasTabs = false

	tk.DrawAt(w, h)
	// tk.setColor(&colorActiveW) // sets the window to Green BG
	tk.setColorWindowTitleActive()

	if tk.window.collapsed {
		// don't show anything but the title bar
		tk.hideWindow()
		return
	}
	tk.placeWidgets(w, h) // compute the sizes & places for each widget

	// this is a test. this should not be needed
	tk.full.w0 = tk.force.w0
	tk.full.h0 = tk.force.h0

	tk.setFullSize()
	tk.Show()
	tk.v.Clear()
	fmt.Fprint(tk.v, "ZZZ"+tk.GetText())
	tk.showWidgets()

	if tk.windowFrame == nil {
		tk.addWindowFrameTK(0 - tk.node.WidgetId)
		tk.windowFrame.node.State.Label = "" // temporary name. blank out when ready for release
		tk.windowFrame.makeTK([]string{""})
	}

	// this seems to correctly create the window frame
	r := tk.getFullSize()
	tk.windowFrame.gocuiSize.w0 = tk.force.w0
	tk.windowFrame.gocuiSize.w1 = r.w1 + 1
	tk.windowFrame.gocuiSize.h0 = tk.force.h0 + 2
	tk.windowFrame.gocuiSize.h1 = r.h1 + 1
	tk.windowFrame.full.w0 = tk.force.w0
	tk.windowFrame.full.w1 = r.w1 + 1
	tk.windowFrame.full.h0 = tk.force.h0 + 2
	tk.windowFrame.full.h1 = r.h1 + 1
	tk.windowFrame.setColorWindowFrame()
	tk.windowFrame.Hide()
	tk.windowFrame.Show()

	// set the window frame below the window widget, but this resizes the window widget it seems
	me.baseGui.SetViewBeneath(tk.windowFrame.cuiName, tk.cuiName, 1)
	// so now we have to resize the window frame, but this moves it to the top?
	me.baseGui.SetView(tk.windowFrame.cuiName, tk.windowFrame.full.w0, tk.windowFrame.full.h0, tk.windowFrame.full.w1, tk.windowFrame.full.h1, 0)

	// so we have to redraw the widgets in the window anyway and then they will appear above he frame
	tk.hideWidgets()
	tk.showWidgets()

	// draw the window title
	tk.setTitle(tk.node.GetLabel())
}

// re-draws the buttons for each of the windows
func redoWindows(nextW int, nextH int) {
	for _, tk := range findWindows() {
		// tk.dumpWidget(fmt.Sprintf("redoWindowsS (%d,%d)", nextW, nextH))
		if tk.window.wasDragged {
			// don't move windows around the user has dragged to a certain location
			tk.makeWindowActive()
		} else {
			w, _ := me.baseGui.Size()
			if nextW > w-20 {
				nextW = 0
				nextH += 4
			}
			// probably a new window?
			tk.redrawWindow(nextW, nextH)
		}
		// tk.dumpWidget(fmt.Sprintf("redoWindowsE (%d,%d)", nextW, nextH))

		// increment the width for the next window
		nextW += tk.gocuiSize.Width() + 10
		// nextH += 10
	}
}

func (tk *guiWidget) addWindowFrameTK(wId int) {
	n := tk.addWindowFrame(wId)
	tk.windowFrame = n.TK.(*guiWidget)
}

func (win *guiWidget) addWindowFrame(wId int) *tree.Node {
	n := new(tree.Node)
	n.WidgetType = widget.Flag
	n.WidgetId = wId
	n.ParentId = 0

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

	tk.node = n
	if tk.node.Parent == nil {
		tk.node.Parent = me.treeRoot
	}
	// copy the data from the action message
	tk.node.State.Label = "windowFrame"

	// set the name used by gocui to the id
	tk.cuiName = fmt.Sprintf("%d DR", wId)

	// tk.color = &colorGroup

	// add this new widget on the binary tree
	tk.parent = win
	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) isWindowActive() bool {
	if !(tk.node.WidgetType == widget.Window || tk.node.WidgetType == widget.Stdout) {
		// only allow Window or the Stdout widgets to be made active
		return false
	}
	return tk.window.active
}

// always redraws at the corner of the gocuiSize box
func (tk *guiWidget) makeWindowActive() {
	if !(tk.node.WidgetType == widget.Window || tk.node.WidgetType == widget.Stdout) {
		// only allow Window or the Stdout widgets to be made active
		return
	}

	if tk.node.WidgetType == widget.Stdout {
		me.stdout.outputOnTop = true
	} else {
		// me.stdout.outputOnTop = false // ?
	}

	// disable and increment all the windows
	for _, tk := range me.allwin {
		tk.window.order += 1
		tk.window.active = false
		// tk.setColor(&colorWindow) // color for inactive windows
		tk.setColorWindowTitle()
	}

	// set this window as the active one
	tk.window.active = true
	tk.window.order = 0

	tk.redrawWindow(tk.gocuiSize.w0, tk.gocuiSize.h0)
	setThingsOnTop() // sets help, Stdout, etc on the top after windows have been redrawn

	/*
		// print out the window list
		for _, tk := range me.allwin {
			log.Info("makeWindowActive() Window", tk.labelN, tk.window.active, tk.window.order)
		}
	*/
}

func (tk *guiWidget) makeTK(ddItems []string) {
	items := strings.Join(ddItems, "\n")
	tk.labelN = items
	tk.SetText(items)
	tk.gocuiSize.w0 = 100
	tk.gocuiSize.w1 = 120
	tk.gocuiSize.h0 = 15
	tk.gocuiSize.h1 = 18
	/*
		var err error
			tk.v, err = me.baseGui.SetView(tk.cuiName,
				tk.gocuiSize.w0,
				tk.gocuiSize.h0,
				tk.gocuiSize.w1,
				tk.gocuiSize.h1, 0)
			if err != nil {
				log.Info("makeTK() err", err)
				return
			}
			if tk.v == nil {
				return
			}
			tk.v.Wrap = true
			tk.v.Frame = true
			tk.v.Clear()
			fmt.Fprint(tk.v, items)
	*/
	tk.Show()
}

func (win *guiWidget) checkWindowClose(w int, h int) bool {
	s := fmt.Sprintf("mouse(%d,%d) ", w, h)
	offW := win.full.w1 - w
	offH := h - win.full.h0
	s += fmt.Sprintf("offset(%d,%d)", offW, offH)
	if (offW < 2) && (offH < 2) {
		log.Info("attempting close on ", s, win.cuiName)
		me.myTree.SendWindowCloseEvent(win.node)
		// store the stdout corner for computing the drag size
		return true
	}
	// log.Info("not attempting close on ", s, win.cuiName)
	return false
}