package profilebtn

import (
	"bytes"
	"image"
	"image/color"
	"image/draw"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
)

var _ fyne.Focusable = (*ProfileBtn)(nil)

type ProfileBtn struct {
	widget.DisableableWidget

	OutlineWidth int
	OutlineColor color.Color

	profileImage      image.Image
	minSizeOverridden bool
	minSizeRequested  fyne.Size
	disabled          bool

	OnTapped func() `json:"-"`
}

// FocusGained is a hook called by the focus handling logic after this object gained the focus.
func (b *ProfileBtn) FocusGained() {
	//	b.focused = true
	b.Refresh()
}

// FocusLost is a hook called by the focus handling logic after this object lost the focus.
func (b *ProfileBtn) FocusLost() {
	//	b.focused = false
	b.Refresh()
}

// TypedRune is a hook called by the input handling logic on text input events if this object is focused.
func (b *ProfileBtn) TypedRune(rune) {
}

// TypedKey is a hook called by the input handling logic on key events if this object is focused.
func (b *ProfileBtn) TypedKey(ev *fyne.KeyEvent) {
	if ev.Name == fyne.KeySpace {
		b.Tapped(nil)
	}
}

func (b *ProfileBtn) Resize(s fyne.Size) {
	b.BaseWidget.Resize(s)
}

func (b *ProfileBtn) Disable() {
	b.disabled = true
}

func (b *ProfileBtn) Ensable() {
	b.disabled = false
}

func (b *ProfileBtn) Disabled() bool {
	return b.disabled
}

func (b *ProfileBtn) Tapped(*fyne.PointEvent) {
	if b.Disabled() {
		return
	}

	//b.tapAnimation()
	b.Refresh()

	if b.OnTapped != nil {
		b.OnTapped()
	}
}

func (b *ProfileBtn) CreateRenderer() fyne.WidgetRenderer {
	return NewProfileBtnRenderer(b)
}

func NewProfileBtnRenderer(b *ProfileBtn) *profileBtnRenderer {
	r := &profileBtnRenderer{
		canvas.NewRasterFromImage(image.NewRGBA(image.Rect(0, 0, 10, 10))),
		b,
	}
	b.ExtendBaseWidget(b)
	return r
}

func NewProfileBtn() *ProfileBtn {
	w := &ProfileBtn{}
	w.ExtendBaseWidget(w)
	w.OutlineWidth = 0
	w.OutlineColor = color.White
	w.SetProfileResource(nil)
	w.minSizeOverridden = false
	w.disabled = false
	return w
}

func (b *ProfileBtn) SetProfileResource(r fyne.Resource) {
	if r != nil {
		i, _, err := image.Decode(bytes.NewReader(r.Content()))
		if err == nil {
			b.profileImage = i
			return
		}
	}
	t, _, _ := image.Decode(bytes.NewReader(resourceProfileBtnPng.StaticContent))
	b.profileImage = t

}

func (b *ProfileBtn) SetMinSize(s fyne.Size) {
	if s.Height > 0 && s.Width > 0 {
		b.minSizeRequested = s
		b.minSizeOverridden = true
		return
	}
	b.minSizeOverridden = false
}

func (b *ProfileBtn) SetProfileImage(i image.Image) {
	b.profileImage = i
}

type profileBtnRenderer struct {
	rast *canvas.Raster
	w    *ProfileBtn
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
func minf(x, y float32) float32 {
	if x < y {
		return x
	}
	return y
}

func (r *profileBtnRenderer) Render(w, h int) image.Image {
	i := image.NewRGBA(image.Rect(0, 0, w, h))
	if r.w.profileImage != nil {
		src := r.w.profileImage
		// convert src to srcRGBA
		srcb := src.Bounds()
		srcRGBA := image.NewRGBA(image.Rect(0, 0, srcb.Dx(), srcb.Dy()))
		draw.Draw(srcRGBA, srcRGBA.Bounds(), src, srcb.Min, draw.Src)

		b := src.Bounds().Size()
		wh := image.NewUniform(r.w.OutlineColor)
		dst := image.NewRGBA(image.Rect(0, 0, b.X, b.Y))
		draw.DrawMask(dst, dst.Bounds(), wh, image.ZP, &circle{image.Point{b.X / 2, b.Y / 2}, (min(b.Y, b.Y) / 2)}, image.ZP, draw.Over)
		if r.w.Disabled() {
			for x := 0; x < srcRGBA.Bounds().Dx(); x++ {
				for y := 0; y < srcRGBA.Bounds().Dx(); y++ {
					c := srcRGBA.RGBA64At(x, y)
					avg := (c.R / 3) + (c.G / 3) + (c.B / 3)
					c = color.RGBA64{avg, avg, avg, c.A}
					srcRGBA.SetRGBA64(x, y, c)
				}
			}
		}
		draw.DrawMask(dst, dst.Bounds(), srcRGBA, image.ZP, &circle{image.Point{b.X / 2, b.Y / 2}, (min(b.Y, b.Y) / 2) - r.w.OutlineWidth}, image.ZP, draw.Over)
		return dst
	} else {
		return i
	}
}

func (r *profileBtnRenderer) MinSize() fyne.Size {
	if r.w.minSizeOverridden {
		return r.w.minSizeRequested
	}
	return fyne.NewSize(theme.Padding()*4, theme.Padding()*4)
}

func (r *profileBtnRenderer) Layout(size fyne.Size) {
	squareSize := fyne.NewSize(minf(size.Width, size.Height), minf(size.Width, size.Height))
	r.rast.Resize(squareSize)
	if squareSize.Width < size.Width {
		r.rast.Move(fyne.NewPos((size.Width-squareSize.Width)/2, 0))
	} else if squareSize.Height < size.Height {
		r.rast.Move(fyne.NewPos(0, (size.Height-squareSize.Height)/2))
	}
}

func (r *profileBtnRenderer) ApplyTheme() {
	r.Refresh()
}

func (r *profileBtnRenderer) BackgprofileColor() color.Color {
	return theme.ButtonColor()
}

func (r *profileBtnRenderer) Refresh() {
	r.rast = canvas.NewRaster(r.Render)
	r.Layout(r.w.Size())
}

func (r *profileBtnRenderer) Destroy() {
}

func (r *profileBtnRenderer) Objects() []fyne.CanvasObject {
	r.Refresh()
	return []fyne.CanvasObject{r.rast}
}
