// Example paste shows how to read text data from the CLIPBOARD selection.
package main

import "os"
import "io"
import "log"
import "github.com/jezek/xgbutil"
import "github.com/jezek/xgb/xproto"
import "github.com/jezek/xgbutil/xprop"
import "github.com/jezek/xgbutil/xevent"
import "github.com/jezek/xgbutil/xwindow"
import "git.tebibyte.media/tomo/xgbsel/v2"

// requestor implements xgbsel.Requestor. It asks for text and outputs it to
// os.Stdout, and any logs to the default logging output (os.Stderr).
type requestor struct {
	window *xwindow.Window
}

func (requestor requestor) Window () *xwindow.Window {
	return requestor.window
}

func (requestor requestor) Success (target xgbsel.Target, data io.ReadCloser) {
	defer data.Close()
	text, _ := io.ReadAll(data)
	log.Println("got clipboard text:")
	os.Stdout.Write(text)
	os.Exit(0)
}

func (requestor requestor) Failure (err error) {
	if err == nil {
		log.Fatalln("no available clipboard data")
	} else {
		log.Fatalln("could not get clipboard:", err)
	}
	os.Exit(1)
}

func (requestor requestor) Choose (available []xgbsel.Target) (xgbsel.Target, bool) {
	log.Println("owner supports these targets:", available)

	// try to find the closest thing to text/plain by converting each target
	// to a MIME type and comparing confidence values
	var bestTarget     xgbsel.Target
	var bestConfidence xgbsel.Confidence
	for _, target := range available {
		mime, confidence := target.ToMime()
		if mime == "text/plain" && confidence > bestConfidence {
			bestConfidence = confidence
			bestTarget     = target
		}
	}

	// if we have any confidence at all, return the result we got
	if bestConfidence > xgbsel.ConfidenceNone {
		return bestTarget, true
	} else {
		return "", false
	}
}

func main () {
	X, err := xgbutil.NewConn()
	if err != nil {
		log.Fatal(err)
	}

	// create window
	window, err := xwindow.Generate(X)
	if err != nil {
		log.Fatalln("could not generate a new window X id:", err)
	}
	window.Create(X.RootWin(), 0, 0, 500, 500, xproto.CwBackPixel, 0xffffffff)

	// get the atom for the clipboard, and the name of the property we want
	// to recieve the selection contents on (which can be anything)
	log.Println("creating request")
	clipboard, _ := xprop.Atm(X, "CLIPBOARD")
	property,  _ := xprop.Atm(X, "DESTINATION")
	request,   _ := xgbsel.NewRequest (
		requestor { window: window },
		clipboard,
		property)

	// listen for events
	window.Listen(xproto.EventMaskPropertyChange)
	xevent.PropertyNotifyFun(request.HandlePropertyNotify).Connect(X, window.Id)
	xevent.SelectionNotifyFun(request.HandleSelectionNotify).Connect(X, window.Id)
	
	log.Println("running main event loop")
	xevent.Main(X)
}