package gioui

import (
	"image"
	"image/color"

	"gioui.org/io/event"
	"gioui.org/io/pointer"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/op/clip"
	"gioui.org/op/paint"
	"gioui.org/unit"
)

type (
	PopupStyle struct {
		Color       color.NRGBA
		CornerRadii struct {
			SE, SW, NW, NE unit.Dp
		}
		Shadow struct {
			Color      color.NRGBA
			N, E, W, S unit.Dp
		}
	}

	PopupWidget struct {
		Style   *PopupStyle
		Visible *bool
	}
)

func Popup(th *Theme, visible *bool) PopupWidget {
	return PopupWidget{
		Style:   &th.Popup.Dialog,
		Visible: visible,
	}
}

func (s PopupWidget) Layout(gtx C, contents layout.Widget) D {
	s.update(gtx)

	if !*s.Visible {
		return D{}
	}

	bg := func(gtx C) D {
		rrect := clip.RRect{
			Rect: image.Rectangle{Max: gtx.Constraints.Min},
			SE:   gtx.Dp(s.Style.CornerRadii.SE),
			SW:   gtx.Dp(s.Style.CornerRadii.SW),
			NW:   gtx.Dp(s.Style.CornerRadii.NW),
			NE:   gtx.Dp(s.Style.CornerRadii.NE),
		}
		rrect2 := rrect
		rrect2.Rect.Min = rrect2.Rect.Min.Sub(image.Pt(gtx.Dp(s.Style.Shadow.W), gtx.Dp(s.Style.Shadow.N)))
		rrect2.Rect.Max = rrect2.Rect.Max.Add(image.Pt(gtx.Dp(s.Style.Shadow.E), gtx.Dp(s.Style.Shadow.S)))
		paint.FillShape(gtx.Ops, s.Style.Shadow.Color, rrect2.Op(gtx.Ops))
		paint.FillShape(gtx.Ops, s.Style.Color, rrect.Op(gtx.Ops))
		area := clip.Rect(image.Rect(-1e6, -1e6, 1e6, 1e6)).Push(gtx.Ops)
		event.Op(gtx.Ops, s.Visible)
		area.Pop()
		area = clip.Rect(rrect2.Rect).Push(gtx.Ops)
		event.Op(gtx.Ops, &dummyTag)
		area.Pop()
		return D{Size: gtx.Constraints.Min}
	}
	macro := op.Record(gtx.Ops)
	dims := layout.Stack{}.Layout(gtx,
		layout.Expanded(bg),
		layout.Stacked(contents),
	)
	callop := macro.Stop()
	op.Defer(gtx.Ops, callop)
	return dims
}

func (s *PopupWidget) update(gtx C) {
	for {
		event, ok := gtx.Event(pointer.Filter{
			Target: s.Visible,
			Kinds:  pointer.Press,
		})
		if !ok {
			break
		}
		e, ok := event.(pointer.Event)
		if !ok {
			continue
		}
		switch e.Kind {
		case pointer.Press:
			*s.Visible = false
		}
	}
}

var dummyTag bool