defmodule BanchanWeb.Components.Form.QuillInput do
  @moduledoc """
  quill.js-based rich text editor.
  """
  use BanchanWeb, :live_component

  alias BanchanWeb.Components.Icon
  alias Surface.Components.Form
  alias Surface.Components.Form.{ErrorTag, Field, Label, TextArea}
  alias Surface.Components.LiveFileInput

  prop(name, :any, required: true)
  prop(opts, :keyword, default: [])
  prop(form, :form, from_context: {Form, :form})
  # TODO: couldn't get this to work, for some reason.
  # prop height, :string, default: "224px"
  prop(label, :string)
  prop(show_label, :boolean, default: true)
  prop(class, :css_class)
  prop(info, :string)
  prop(caption, :string)
  prop(upload, :struct)
  prop(cancel_upload, :event)

  data(dragging, :boolean, default: false)

  def update(assigns, socket) do
    {:ok, assign(socket, assigns) |> push_event("set_rich_text", %{id: assigns.id <> "_hook"})}
  end

  def handle_event("dragstart", _, socket) do
    {:noreply, assign(socket, dragging: true)}
  end

  def handle_event("dragend", _, socket) do
    {:noreply, assign(socket, dragging: false)}
  end

  def error_to_string(:too_large), do: "Too large"
  def error_to_string(:too_many_files), do: "You have selected too many files"
  def error_to_string(:not_accepted), do: "You have selected an unacceptable file type"

  def render(assigns) do
    ~F"""
    <Field class="grid grid-cols-1 gap-1 field" name={@name}>
      {#if @show_label}
        <Label class="p-0 label">
          <span class="flex flex-row items-center gap-1 label-text">
            {@label || Phoenix.Naming.humanize(@name)}
            {!--
            {#if @info}
              <div class="tooltip tooltip-right" data-tip={@info}>
                <Icon
                  name="info"
                  size="4"
                  label="tooltip"
                  class="opacity-50 hover:opacity-100 active:opacity-100"
                />
              </div>
            {/if}
            --}
          </span>
        </Label>
      {/if}
      {#if @caption}
        <div class="text-sm text-opacity-50 help text-base-content">
          {@caption}
        </div>
      {/if}
      <div class="control">
        <div class={"relative", "has-upload": !is_nil(@upload)}>
          <TextArea form={@form} field={@name} class="hidden input-textarea" opts={@opts} />
          <div
            class={@class}
            phx-drop-target={@upload && @upload.ref}
            phx-update="ignore"
            :hook="QuillInput"
            id={@id <> "_hook"}
          >
            <div id={@id <> "-editor"} phx-update="ignore" class="object-cover w-full h-full editor" />
          </div>
          {#if @upload}
            <LiveFileInput
              class="w-full text-sm rounded-t-none file-input file-input-bordered"
              upload={@upload}
            />
            {#if @dragging}
              <div class="absolute w-full h-full border-2 border-dashed opacity-25 bg-neutral" />
              <div class="absolute w-full h-full my-auto text-center">
                Drop Files Here <Icon name="file-up" size="4" label="upload file" />
              </div>
            {/if}
          {/if}
        </div>
      </div>
      <ErrorTag class="help text-error" />
      {#if @upload}
        <ul>
          {#for entry <- @upload.entries}
            <li>
              <button type="button" class="text-2xl" :on-click={@cancel_upload} phx-value-ref={entry.ref}>&times;</button>
              {entry.client_name}
              <progress class="progress progress-primary" value={entry.progress} max="100">{entry.progress}%</progress>
              {#for err <- upload_errors(@upload, entry)}
                <p class="text-error">{error_to_string(err)}</p>
              {/for}
            </li>
          {/for}
        </ul>
        {#for err <- upload_errors(@upload)}
          <p class="text-error">{error_to_string(err)}</p>
        {/for}
      {/if}
    </Field>
    """
  end
end
