package clipboard

import (
	"bufio"
	"context"
	"os/exec"
	"strings"
)

type WaylandClipboard struct{}

func NewWayland() (*WaylandClipboard, error) {
	// Check if wl-paste is available
	if _, err := exec.LookPath("wl-paste"); err != nil {
		return nil, err
	}
	if _, err := exec.LookPath("wl-copy"); err != nil {
		return nil, err
	}
	return &WaylandClipboard{}, nil
}

func (c *WaylandClipboard) Read() (string, error) {
	cmd := exec.Command("wl-paste", "--no-newline")
	output, err := cmd.Output()
	if err != nil {
		// wl-paste returns error if clipboard is empty
		return "", nil
	}
	return string(output), nil
}

func (c *WaylandClipboard) Write(content string) error {
	cmd := exec.Command("wl-copy")
	cmd.Stdin = strings.NewReader(content)
	return cmd.Run()
}

func (c *WaylandClipboard) Watch(ctx context.Context) <-chan string {
	out := make(chan string)

	go func() {
		defer close(out)

		// Use wl-paste --watch to detect clipboard changes
		// When clipboard changes, it runs "echo x" which outputs a single line
		// Then we read the full clipboard content separately
		cmd := exec.CommandContext(ctx, "wl-paste", "--watch", "echo", "x")
		stdout, err := cmd.StdoutPipe()
		if err != nil {
			return
		}

		if err := cmd.Start(); err != nil {
			return
		}

		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			select {
			case <-ctx.Done():
				cmd.Process.Kill()
				return
			default:
				// Clipboard changed, read full content
				content, err := c.Read()
				if err == nil && content != "" {
					out <- content
				}
			}
		}

		cmd.Wait()
	}()

	return out
}
