package ui

import (
	"context"
	"io"
	"log"
	"os/exec"
	"time"

	"github.com/eiannone/keyboard"
)

const (
	CMD_FIM            = "/usr/local/bin/pf-fim.sh"
	SLIDESHOW_INTERVAL = 300 * time.Second
)

func Slideshow() {
	// fim placeholder so we can operate on it when a exit slideshow is received
	var fim *exec.Cmd = nil

	// Run slideshow
	fim = exec.Command(CMD_FIM)

	// Setup stdin for fim to control slideshow
	stdin, err := fim.StdinPipe()
	if err != nil {
		log.Fatalf("Error getting fim stdin : %s", err)
	}

	// Advance slideshow every interval as defined in const()
	ticker := time.NewTicker(SLIDESHOW_INTERVAL)
	stop_ticker := make(chan struct{})
	go func() {
		for {
			select {
			case <-ticker.C:
				_, err = io.WriteString(stdin, "n")
				if err != nil {
					log.Fatalf("Error advancing slides : %s", err)
				}
			case <-stop_ticker:
				ticker.Stop()
				stdin.Close()
				return
			}
		}
	}()

	// Start watching for key strokes and echo them back to stdout
	keysEvents, err := keyboard.GetKeys(10)
	if err != nil {
		log.Fatalf("Error setting up keyboard listener : %s", err)
	}
	// NOT deferring keyboard.close as we do that by hand further down when fim exits ahead of showing the config UI

	// Goroutine for tracking which keys are pressed and controlling fim if appropriate
	keyboardCtx, keyboardCancel := context.WithCancel(context.Background())
	go func(keyboardCtx context.Context) {
		for {
			select {
			case <-keyboardCtx.Done():
				return
			case event := <-keysEvents:
				if event.Err != nil {
					log.Fatalf("Error listening to key events : %s", err)
				}
				log.Printf("You pressed: key %X\n", event.Key)

				// Keys for fim event management (previous/next in particular)
				fimKey := ""
				if event.Key == keyboard.KeyArrowLeft || event.Key == keyboard.KeyArrowDown {
					fimKey = "p"
				}
				if event.Key == keyboard.KeyArrowRight || event.Key == keyboard.KeyArrowUp {
					fimKey = "n"
				}

				// Exit fim and move to the config UI
				if event.Key == keyboard.KeyEsc || event.Key == keyboard.KeyEnter || event.Key == keyboard.KeySpace {
					if fim != nil { // Just in case someone lays on exit key or similar during startup
						if err := fim.Process.Kill(); err != nil {
							log.Fatalf("failed to kill fim : %s", err)
						}
					}
					break
				}

				// Control fim if we received a valid key for next/previous slide
				if fimKey != "" {
					log.Printf("Sending key to fim : %s", fimKey)
					_, err = io.WriteString(stdin, fimKey)
					if err != nil {
						log.Fatalf("Error controlling fim : %s", err)
					}
					ticker.Reset(SLIDESHOW_INTERVAL)
				}
			}
		}
	}(keyboardCtx)

	// Run fim
	// if err := fim.Run(); err != nil {
	// 	// Unwrap the error a bit so we can find out if a signal killed fim or something else
	// 	// An exit code of -1 means the program didn't exit in time or was terminated by a signal (per the docs)
	// 	if exitError, ok := err.(*exec.ExitError); ok && exitError.ExitCode() != -1 {
	// 		log.Fatalf("Error running fim : %s", err)
	// 	}
	// }

	// Stop fim slideshow advancing go routine
	close(stop_ticker)

	// Stop listening to keyboard events
	keyboard.Close()
	keyboardCancel()

}
