lib/icons/icon_button/icon_button.ex

defmodule FloUI.Icon.Button do
  @moduledoc """
  ## Usage in SnapFramework

  Render a button with an icon.

  data is a string for the tooltip.

  ``` elixir
  <%= component FloUI.Icon.Button,
      "tooltip text",
      id: :btn_icon
  do %>
    <%= component FloUI.Icon,
        {:flo_ui, "path_to_icon"}
    %>
  <% end %>
  ```
  """

  @default_theme FloUI.Theme.preset(:primary)

  use SnapFramework.Component,
    name: :icon_button,
    template: "lib/icons/icon_button/icon_button.eex",
    controller: FloUI.Icon.ButtonController,
    assigns: [
      id: nil,
      icon: nil,
      label: nil,
      showing_highlight: false,
      showing_tooltip: false
    ],
    opts: []

  defcomponent(:icon_button, :any)

  watch([:children])

  use_effect([assigns: [showing_highlight: :any]],
    run: [:on_highlight_change]
  )

  use_effect([assigns: [showing_tooltip: :any]],
    run: [:on_show_tooltip_change]
  )

  # DEPRECATED
  # use_effect [on_click: [@assigns[:id]]], :cont, []

  @impl true
  def setup(%{assigns: %{data: nil, opts: opts}} = scene) do
    # Logger.debug(inspect state, pretty: true)
    scene
    |> assign(
      id: scene.assigns.opts[:id] || nil,
      theme: get_theme(opts)
    )
  end

  def setup(%{assigns: %{data: label, opts: opts}} = scene) do
    request_input(scene, [:cursor_pos])
    scene
    |> assign(
      id: scene.assigns.opts[:id] || nil,
      label: label,
      theme: get_theme(opts)
    )
  end

  @impl true
  def bounds(_data, _opts) do
    {0.0, 0.0, 50, 50}
  end

  @impl true
  def process_update(data, opts, scene) do
    {:noreply, assign(scene, data: data, children: opts[:children], opts: opts)}
  end

  @impl true
  def process_input({:cursor_button, {:btn_left, 1, _, _}}, :btn, scene) do
    {:noreply, scene}
  end

  def process_input({:cursor_button, {:btn_left, 0, _, _}}, :btn, scene) do
    send_parent_event(scene, {:click, scene.assigns.id})
    {:noreply, scene}
  end

  def process_input({:cursor_pos, _}, :btn, %{assigns: %{label: nil}} = scene) do
    capture_input(scene, [:cursor_pos])
    {:noreply, assign(scene, showing_highlight: true, showing_tooltip: false)}
  end

  def process_input({:cursor_pos, _}, :btn, scene) do
    capture_input(scene, [:cursor_pos])
    {:noreply, assign(scene, showing_highlight: true, showing_tooltip: true)}
  end

  def process_input({:cursor_pos, _}, _, scene) do
    release_input(scene)
    {:noreply, assign(scene, showing_highlight: false, showing_tooltip: false)}
  end

  def process_input(_event, _, scene) do
    {:noreply, scene}
  end

  defp get_theme(opts) do
      case opts[:theme] do
        nil -> @default_theme
        :dark -> @default_theme
        :light -> @default_theme
        theme -> theme
      end
      |> FloUI.Theme.normalize()
  end
end