package widget

import (
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/internal/widget"
	"fyne.io/fyne/v2/theme"
)

type iconRenderer struct {
	widget.BaseRenderer
	raster *canvas.Image

	image *Icon
}

func (i *iconRenderer) MinSize() fyne.Size {
	return fyne.NewSquareSize(i.image.Theme().Size(theme.SizeNameInlineIcon))
}

func (i *iconRenderer) Layout(size fyne.Size) {
	if len(i.Objects()) == 0 {
		return
	}

	i.Objects()[0].Resize(size)
}

func (i *iconRenderer) Refresh() {
	if i.image.Resource == i.image.cachedRes {
		return
	}

	i.image.propertyLock.RLock()
	i.raster.Resource = i.image.Resource
	i.image.cachedRes = i.image.Resource

	if i.image.Resource == nil {
		i.raster.Image = nil // reset the internal caching too...
	}
	i.image.propertyLock.RUnlock()

	i.raster.Refresh()
}

// Icon widget is a basic image component that load's its resource to match the theme.
type Icon struct {
	BaseWidget

	Resource  fyne.Resource // The resource for this icon
	cachedRes fyne.Resource
}

// SetResource updates the resource rendered in this icon widget
func (i *Icon) SetResource(res fyne.Resource) {
	i.Resource = res
	i.Refresh()
}

// MinSize returns the size that this widget should not shrink below
func (i *Icon) MinSize() fyne.Size {
	i.ExtendBaseWidget(i)
	return i.BaseWidget.MinSize()
}

// CreateRenderer is a private method to Fyne which links this widget to its renderer
func (i *Icon) CreateRenderer() fyne.WidgetRenderer {
	i.ExtendBaseWidget(i)
	i.propertyLock.RLock()
	defer i.propertyLock.RUnlock()

	img := canvas.NewImageFromResource(i.Resource)
	img.FillMode = canvas.ImageFillContain

	r := &iconRenderer{image: i, raster: img}
	r.SetObjects([]fyne.CanvasObject{img})
	i.cachedRes = i.Resource
	return r
}

// NewIcon returns a new icon widget that displays a themed icon resource
func NewIcon(res fyne.Resource) *Icon {
	icon := &Icon{}
	icon.ExtendBaseWidget(icon)
	icon.SetResource(res) // force the image conversion

	return icon
}
