package ui

import (
	"fmt"
	"strconv"
)

func (d *Driver) realId(id string) string {
	return fmt.Sprintf("%v:%v", d.menu.Name, id)
}

func (d *Driver) Value(id string, into *string) error {
	for _, valueable := range d.allValueables() {
		if valueable.id() == d.realId(id) {
			*into = valueable.value()
			return nil
		}
	}

	return fmt.Errorf("Couldn't find valueable widget %v:%v", d.menu.Name, id)
}

func (d *Driver) SetValue(id, value string) error {
	for _, valueable := range d.allValueables() {
		if valueable.id() == d.realId(id) {
			valueable.setValue(value)
			return nil
		}
	}

	return fmt.Errorf("Couldn't find valueable widget %v:%v", d.menu.Name, id)
}

func (d *Driver) ValueBool(id string, into *bool) error {
	var vStr string
	if err := d.Value(id, &vStr); err != nil {
		return err
	}

	*into = vStr == "1"
	return nil
}

func (d *Driver) SetValueBool(id string, value bool) error {
	vStr := "0"
	if value {
		vStr = "1"
	}

	return d.SetValue(id, vStr)
}

func (d *Driver) SetFreeze(id string, value bool) error {
	for _, freezable := range d.allFreezables() {
		if freezable.id() == d.realId(id) {
			freezable.setFreezeState(value)
			return nil
		}
	}

	return fmt.Errorf("Couldn't find clickable widget %v:%v", d.menu.Name, id)
}

func (d *Driver) ToggleActive(locator string) error {
	if widget := d.findWidget(locator); widget != nil {
		widget.Active = !widget.Active

		return nil
	}

	return fmt.Errorf("Couldn't find activatable widget %v to toggle", locator)
}

func (d *Driver) SetActive(locator string, value bool) error {
	if widget := d.findWidget(locator); widget != nil {
		widget.Active = value

		return nil
	}

	return fmt.Errorf("Couldn't find activeatable widget %v to set to %v", locator, value)
}

func (d *Driver) OnClick(id string, f func()) error {
	for _, clickable := range d.allClickables() {
		if clickable.id() == d.realId(id) {
			clickable.onClick(f)
			return nil
		}
	}

	return fmt.Errorf("Couldn't find clickable widget %v:%v", d.menu.Name, id)
}

// FIXME: HURK. Surely I'm missing something? steps is value:offset
func (d *Driver) ConfigureSlider(id string, steps map[int]int) error {
	for _, clickable := range d.activeClickables() {
		if slider, ok := clickable.(*slider); ok && slider.id() == d.realId(id) {
			slider.steps = steps

			return nil
		}
	}

	return fmt.Errorf("Couldn't find slider %v:%v", d.menu.Name, id)
}

func (d *Driver) ValueInt(id string, into *int) error {
	var vStr string
	if err := d.Value(id, &vStr); err != nil {
		return err
	}

	value, err := strconv.Atoi(vStr)
	if err != nil {
		return err
	}

	*into = value

	return nil
}

func (d *Driver) SetValueInt(id string, value int) error {
	vStr := strconv.Itoa(value)

	return d.SetValue(id, vStr)
}
