package button

import (
	"github.com/diamondburned/cchat"
	"github.com/diamondburned/cchat-gtk/internal/gts"
	"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
	"github.com/diamondburned/cchat-gtk/internal/ui/primitives/menu"
	"github.com/diamondburned/cchat-gtk/internal/ui/rich"
	"github.com/diamondburned/cchat/text"
)

type ToggleButtonImage struct {
	rich.ToggleButtonImage

	extraMenu []menu.Item
	menu      *menu.LazyMenu

	clicked func(bool)
	readcss primitives.ClassEnum

	err    error
	icon   string // whether or not the button has an icon
	iconSz int
}

var _ cchat.IconContainer = (*ToggleButtonImage)(nil)

var serverButtonCSS = primitives.PrepareCSS(`
	.read      { color: alpha(@theme_fg_color, 0.5) }
	.unread    { color: @theme_fg_color }
	.mentioned { color: red }
`)

func NewToggleButtonImage(content text.Rich) *ToggleButtonImage {
	b := rich.NewToggleButtonImage(content)
	b.Show()

	tb := &ToggleButtonImage{
		ToggleButtonImage: *b,

		clicked: func(bool) {},
		menu:    menu.NewLazyMenu(b.ToggleButton),
	}
	tb.Connect("clicked", func() { tb.clicked(tb.GetActive()) })
	primitives.AttachCSS(tb, serverButtonCSS)

	return tb
}

func (b *ToggleButtonImage) SetClicked(clicked func(bool)) {
	b.clicked = clicked
}

func (b *ToggleButtonImage) SetClickedIfTrue(clickedIfTrue func()) {
	b.clicked = func(clicked bool) {
		if clicked {
			clickedIfTrue()
		}
	}
}

func (b *ToggleButtonImage) SetNormalExtraMenu(items []menu.Item) {
	b.extraMenu = items
	b.SetNormal()
}

func (b *ToggleButtonImage) SetNormal() {
	b.SetLabelUnsafe(b.GetLabel())
	b.menu.SetItems(b.extraMenu)

	if b.icon != "" {
		b.Image.SetPlaceholderIcon(b.icon, b.Image.Size())
	}
}

func (b *ToggleButtonImage) SetLoading() {
	b.SetLabelUnsafe(b.GetLabel())

	// Reset the menu.
	b.menu.SetItems(b.extraMenu)

	if b.icon != "" {
		b.Image.SetPlaceholderIcon("content-loading-symbolic", b.Image.Size())
	}
}

func (b *ToggleButtonImage) SetFailed(err error, retry func()) {
	b.Label.SetMarkup(rich.MakeRed(b.GetLabel()))

	// Add a retry button, if any.
	b.menu.Reset()
	b.menu.AddItems(menu.SimpleItem("Retry", retry))
	b.menu.AddItems(b.extraMenu...)

	// If we have an icon set, then we can use the failed icon.
	if b.icon != "" {
		b.Image.SetPlaceholderIcon("computer-fail-symbolic", b.Image.Size())
	}
}

func (b *ToggleButtonImage) SetUnreadUnsafe(unread, mentioned bool) {
	switch {
	case unread:
		b.readcss.SetClass(b, "unread")
	case mentioned:
		b.readcss.SetClass(b, "mentioned")
	default:
		b.readcss.SetClass(b, "read")
	}
}

func (b *ToggleButtonImage) SetPlaceholderIcon(iconName string, iconSzPx int) {
	b.icon = iconName
	b.Image.SetPlaceholderIcon(iconName, iconSzPx)
}

func (b *ToggleButtonImage) SetIcon(url string) {
	gts.ExecAsync(func() { b.SetIconUnsafe(url) })
}

func (b *ToggleButtonImage) SetIconUnsafe(url string) {
	b.icon = ""
	b.Image.SetIconUnsafe(url)
}