defmodule GorgonWeb.HuskLive.FormComponent do
  use GorgonWeb, :live_component

  alias Gorgon.Forge.Husk

  @impl true
  def render(assigns) do
    ~H"""
    <div>
      <.header>
        <%= @title %>
        <:subtitle>
          {{copy}}
        </:subtitle>
      </.header>

      <.simple_form
        for={@form}
        id="husk-form"
        phx-target={@myself}
        phx-change="validate"
        phx-submit="save"
      >
        <.input field={@form[:name]} label="Name" />
        <.input field={@form[:twitch_user]} label="Twitch user" />

        <p>
          Go
          <.a _target="blank" navigate="https://twitchapps.com/tmi/">here</.a>
          while logged in with your husk's account to get an oauth token.
        </p>

        <.input field={@form[:twitch_pass]} label="Oauth token" />
        <!--  <.live_component
          module={GorgonWeb.HuskLive.StringArrayComponent}
          id={@husk.id || :new}
          rows={@form.data.twitch_channels}
          husk={@husk}
          current_user={@current_user}
        />
    -->
        <label class="block text-sm font-semibold leading-6 text-purble-800 dark:text-purble-200">
          Twitch channels <%= @hideaddbutton %>
        </label>
        <%= if AshPhoenix.Form.value(@form, :twitch_channels) != nil do %>
          <%= for {channel, index} <- Enum.with_index(AshPhoenix.Form.value(@form, :twitch_channels)) do %>
            <div class="flex !mt-0">
              <.input phx-value-index={index} required name="form[twitch_channels][]" value={channel} />
              <.button
                type="button"
                class={[
                  "mt-2 ml-2 px-2 bg-transparent text-red-500 hover:bg-red-500 hover:text-white",
                  @hidedeletebutton && "hidden"
                ]}
                phx-click="delete_channel"
                phx-value-index={index}
                phx-target={@myself}
              >
                <.icon name="hero-x-circle"></.icon>
              </.button>
            </div>
          <% end %>
        <% else %>
          its nil!!!
        <% end %>

        <.button
          class={["!mt-2", @hideaddbutton && "hidden"]}
          type="button"
          phx-click="add_channel"
          phx-target={@myself}
        >
          add channel
        </.button>

        <:actions>
          <.button phx-disable-with="Saving...">Save Husk</.button>
        </:actions>
      </.simple_form>
    </div>
    """
  end

  @impl true
  def handle_event("delete_channel", %{"index" => index}, socket) do
    # TODO: dont let the last one get deleted
    IO.inspect(socket.assigns.form.params)

    new_form =
      AshPhoenix.Form.update_form(socket.assigns.form.source, "form", fn child_form ->
        new_value =
          AshPhoenix.Form.value(socket.assigns.form, :twitch_channels)
          |> List.delete_at(String.to_integer(index))

        AshPhoenix.Form.validate(
          socket.assigns.form,
          Map.put(AshPhoenix.Form.params(socket.assigns.form), "twitch_channels", new_value)
        )
      end)

    socket =
      socket
      |> assign(:form, new_form)
      |> assign(hideaddbutton: hideaddbutton?(AshPhoenix.Form.params(new_form)))
      |> assign(hidedeletebutton: hidedeletebutton?(AshPhoenix.Form.params(new_form)))

    {:noreply, socket}
  end

  @impl true
  def handle_event("add_channel", %{}, socket) do
    new_form =
      AshPhoenix.Form.update_form(socket.assigns.form.source, "form", fn child_form ->
        case AshPhoenix.Form.value(socket.assigns.form, :twitch_channels) do
          nil ->
            new_value = [""]

            AshPhoenix.Form.validate(
              socket.assigns.form,
              Map.put(AshPhoenix.Form.params(socket.assigns.form), "twitch_channels", new_value)
            )

          _ ->
            new_value = AshPhoenix.Form.value(socket.assigns.form, :twitch_channels) ++ [""]

            AshPhoenix.Form.validate(
              socket.assigns.form,
              Map.put(AshPhoenix.Form.params(socket.assigns.form), "twitch_channels", new_value)
            )
        end
      end)

    socket =
      socket
      |> assign(:form, new_form)
      |> assign(hideaddbutton: true)
      |> assign(hidedeletebutton: false)

    {:noreply, socket}
  end

  # like mount but for livecomponents its called update??
  @impl true
  def update(assigns, socket) do
    # form =
    #   AshPhoenix.Form.for_action(Husk, assigns.action, api: Husk)
    #   |> to_form()

    form = actionify_form(assigns)

    IO.inspect(form)
    IO.inspect(form.data)
    IO.inspect(Map.from_struct(form.data))

    socket =
      socket
      |> assign(assigns)
      |> assign(form: form)
      |> assign(hideaddbutton: false)
      |> assign(hidedeletebutton: false)

    # trying to make it not show delete if there's only one entry on first mount
    # |> assign(hidedeletebutton: hidedeletebutton?(Map.from_struct(form.data)))

    {:ok, socket}
  end

  defp actionify_form(assigns) do
    case assigns.action do
      :new ->
        AshPhoenix.Form.for_create(Husk, :create,
          api: Gorgon.Forge,
          actor: assigns.current_user
        )
        |> to_form()

      :edit ->
        AshPhoenix.Form.for_update(assigns.husk, :update,
          api: Gorgon.Forge,
          actor: assigns.current_user
        )
        |> to_form
    end
  end

  @impl true
  def handle_event("validate", %{"form" => husk_params}, socket) do
    form = socket.assigns.form |> AshPhoenix.Form.validate(husk_params)

    socket = socket |> assign(form: form) |> assign(hideaddbutton: hideaddbutton?(husk_params))

    {:noreply, socket}
  end

  defp hideaddbutton?(husk_params) do
    IO.inspect(husk_params)

    case husk_params["twitch_channels"] do
      [] ->
        false

      _ ->
        if husk_params["twitch_channels"] |> List.last() == "" ||
             husk_params["twitch_channels"] |> List.last() == nil do
          true
        else
          false
        end
    end
  end

  defp hidedeletebutton?(params) do
    if length(params["twitch_channels"]) < 2 do
      true
    end
  end

  def handle_event("save", %{"form" => form}, socket) do
    save_husk(socket, socket.assigns.action, form)
  end

  # save a new
  defp save_husk(socket, :new, params) do
    form = AshPhoenix.Form.validate(socket.assigns.form, params)

    case AshPhoenix.Form.submit(form) do
      {:ok, husk} ->
        notify_parent({:saved, husk})

        {:noreply,
         socket
         |> put_flash(:info, "Husk created successfully")
         # socket.assigns.patch)}
         |> push_navigate(to: ~p"/husks/#{husk}")}

      {:error, form} ->
        {:noreply, assign(socket, form)}

      other ->
        IO.inspect(other, label: "other")
    end
  end

  # save a edit
  defp save_husk(socket, :edit, params) do
    form = AshPhoenix.Form.validate(socket.assigns.form, params)

    case AshPhoenix.Form.submit(form) do
      {:ok, husk} ->
        notify_parent({:saved, husk})

        {:noreply,
         socket
         |> put_flash(:info, "Husk updated successfully")
         |> push_patch(to: socket.assigns.patch)}

      {:error, form} ->
        {:noreply, assign(socket, form)}
    end
  end

  defp notify_parent(msg), do: send(self(), {__MODULE__, msg})
end
Edit Report
Pub: 29 Mar 2023 21:05 UTC
Views: 63