package main

import (
	"image/color"
	"log"
	"strings"
	"time"

	"opslag.de/schobers/geom"
	"opslag.de/schobers/zntg/addons/drop"
	_ "opslag.de/schobers/zntg/allg5ui" // import the renderer for the UI

	"opslag.de/schobers/zntg/ui"
)

type dropFiles struct {
	ui.StackPanel

	ctx   ui.Context
	files *ui.Paragraph
	ping  *ping
}

type ping struct {
	ui.OverlayBase

	circle   ui.Texture
	position geom.PointF32
	tick     time.Time
}

func (p *ping) Render(ctx ui.Context) {
	elapsed := time.Since(p.tick)
	const animationDuration = 500 * time.Millisecond
	if elapsed > animationDuration {
		return
	}
	tint := color.Gray{Y: uint8(elapsed * 255 / animationDuration)}
	center := geom.PtF32(float32(p.circle.Width()), float32(p.circle.Height())).Mul(.5)
	ctx.Renderer().DrawTexturePointOptions(p.circle, p.position.Sub(center), ui.DrawOptions{Tint: tint})
	ctx.Animate()
}

func (d *dropFiles) WindowHandle() uintptr { return d.ctx.Renderer().WindowHandle() }

func (d *dropFiles) FilesDropped(position geom.PointF32, files []string) {
	d.files.Text = "Files dropped:\n" + strings.Join(files, "\n")
	d.ping.tick = time.Now()
	d.ping.position = position
	d.ctx.Animate()
}

func newCircle() ui.ImageSource {
	const side = 16
	center := geom.PtF32(.5*side, .5*side)
	return &ui.AlphaPixelImageSource{
		ImageAlphaPixelTestFn: func(p geom.PointF32) uint8 {
			dist := p.Distance(center)
			if dist < 7 {
				return 255
			} else if dist > 8 {
				return 0
			}
			return uint8((8 - dist) * 255 * 0.5)
		},
		Size: geom.Pt(side, side),
	}
}

func (d *dropFiles) Init(ctx ui.Context) error {
	d.ctx = ctx

	_, err := ctx.Fonts().CreateFontPath("default", "../resources/font/OpenSans-Regular.ttf", 14)
	if err != nil {
		return err
	}

	d.files = ui.BuildParagraph("", nil)

	pingCircle, err := ctx.Renderer().CreateTexture(newCircle())
	if err != nil {
		return err
	}
	d.ping = &ping{circle: pingCircle}
	ctx.Overlays().AddOnTop("ping", d.ping, true)

	d.Background = color.White
	d.Children = []ui.Control{
		&ui.Label{Text: "Drop files on this window!"},
		d.files,
	}
	return nil
}

func run() error {
	var render, err = ui.NewRendererDefault("Files Drop Example", 800, 600)
	if err != nil {
		return err
	}
	defer render.Destroy()

	return ui.RunWait(render, ui.DefaultStyle(), &dropFiles{}, true)
}

func main() {
	var err = run()
	if err != nil {
		log.Fatal(err)
	}
}