//gjcarro:pjcarrlugin

// Copyright 2014 The gocui Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.


package main

import (
	"errors"
	"os"
	"runtime/debug"

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

func queueToolkitClose() {
	me.baseGui.Close()
}

func queueSetChecked(n *tree.Node, b bool) {
	setChecked(n, b)
}

// sets defaults and establishes communication
// to this toolkit from the wit/gui golang package
func init() {
	log.Log(INFO, "Init() of awesome-gocui")

	// init the config struct default values
	Set(&me, "default")

	// Set(&me, "dense")

	me.myTree = tree.New()
	me.myTree.PluginName = "gocui"

	me.myTree.NodeAction = newaction
	me.myTree.Add = newAdd
	me.myTree.SetTitle = newSetTitle
	me.myTree.SetLabel = newSetLabel
	me.myTree.SetText = newSetText
	me.myTree.AddText = newAddText
	me.myTree.SetChecked = queueSetChecked
	me.myTree.ToolkitClose = queueToolkitClose

	log.Log(NOW, "Init() start pluginChan")
	log.Sleep(.1) // probably not needed, but in here for now under development
	go mainGogui()
	log.Sleep(.1) // probably not needed, but in here for now under development
}

func standardExit() {
	log.Log(NOW, "standardExit() doing baseGui.Close()")
	me.baseGui.Close()
	log.Log(NOW, "standardExit() doing outf.Close()")
	outf.Close()
	// log(true, "standardExit() setOutput(os.Stdout)")
	// setOutput(os.Stdout)
	log.Log(NOW, "standardExit() send back Quit()")
	// go sendBackQuit() // don't stall here in case the
	// induces a delay in case the callback channel is broken
	log.Sleep(1)
	log.Log(NOW, "standardExit() exit()")
	os.Exit(0)
}

func standardClose() {
	log.Log(NOW, "standardExit() doing baseGui.Close()")
	me.baseGui.Close()
	log.Log(NOW, "standardExit() doing outf.Close()")
	outf.Close()
	os.Stdin = os.Stdin
	os.Stdout = os.Stdout
	os.Stderr = os.Stderr
	log.Log(NOW, "standardExit() send back Quit()")
}

var outf *os.File

func main() {
}

var origStdout *os.File
var origStderr *os.File

func mainGogui() {
	defer func() {
		if r := recover(); r != nil {
			log.Warn("YAHOOOO Recovered in guiMain application:", r)
			log.Warn("Recovered from panic:", r)
			me.baseGui.Close()
			log.CaptureMode(nil)
			log.Warn("YAHOOOO Recovered in guiMain application:", r)
			log.Warn("Recovered from panic:", r)
			me.myTree.SendToolkitPanic()

			return
		}
	}()

	var err error

	outf, err = os.OpenFile("/tmp/captureMode.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Error(err, "error opening file: %v")
		os.Exit(0)
	}
	origStdout = os.Stdout
	os.Stdout = outf
	defer outf.Close()

	log.CaptureMode(outf)

	gocuiMain()
}

// This initializes the gocui package
// it runs SetManagerFunc which passes every input
// event (keyboard, mouse, etc) to the function "gocuiEvent()"
func gocuiMain() {
	defer func() {
		if r := recover(); r != nil {
			log.Warn("YAHOOOO Recovered in gocuiMain()", r)
			log.Warn("Recovered from panic:", r)
			me.baseGui.Close()

			// allow gocui to close if possible, then print stack
			log.Sleep(1)
			os.Stdout = origStdout
			os.Stderr = origStderr
			me.myTree.SendToolkitPanic()
			log.Warn("Stack trace:")
			debug.PrintStack()
			// panic("BUMMER 2")

			// attempt to switch to the nocui toolkit
			log.Sleep(1)
			me.myTree.SendToolkitLoad("nocui")
			log.Sleep(3)
			me.myTree.SendToolkitLoad("nocui")
			// panic("BUMMER")
			return
		}
	}()
	g, err := gocui.NewGui(gocui.OutputNormal, true)
	if err != nil {
		return
	}
	defer g.Close()

	me.baseGui = g

	g.Cursor = true
	g.Mouse = true

	// this sets the function that is run on every event. For example:
	// When you click the mouse, move the mouse, or press a key on the keyboard
	// This is equivalent to xev or similar to cat /dev/input on linux
	g.SetManagerFunc(gocuiEvent)

	if err := defaultKeybindings(g); err != nil {
		// normally panic here
		log.Log(NOW, "defaultKeybindings(g) panic err =", err)
		panic("gocuiTKdefaultkeybindings OOPS")
	}

	if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
		log.Log(NOW, "g.MainLoop() panic err =", err)
		// normally panic here
		panic("gocuiTKmainloop OOPS")
	}
}