defmodule OutlookWeb.ArticleLive.New do
  use OutlookWeb, :live_view

  import OutlookWeb.ArticleLive.NewComponents

  alias OutlookWeb.ArticleLive.FormComponent
  alias Outlook.{Articles,Authors,HtmlPreparations,InternalTree}
  alias Articles.{Article,RawHtmlInput}

  require Logger

  @impl true
  def mount(_params, _session, socket) do
    {:ok,
      socket
      |> assign(:page_title, "New Article")
      |> assign(:raw_html_input, %RawHtmlInput{})
      |> assign(:changeset, Articles.change_raw_html_input(%RawHtmlInput{}))
      |> assign(:selected_els, [])
      |> assign(:selected_tunits, [])
      |> assign(:step, :import_raw_html)}
  end

  @impl true
  def handle_params(%{"author_id" => author_id}, _, socket) do
    author = Authors.get_author!(author_id)
    article = %Article{author_id: author.id}
    {:noreply,
     socket
     |> assign(:menu_entries, InternalTree.tunit_modifiers()) # REMOVE ME!
     |> assign(:author, author)
     |> assign(:article, article)}
  end

  @impl true
  def handle_event("validate_raw_html_input", %{"raw_html_input" => raw_html_input_params}, socket) do
    changeset = validate_raw_html_input(raw_html_input_params, socket)
    {:noreply, assign(socket, :changeset, changeset)}
  end

  def handle_event("convert_raw_html_input", %{"raw_html_input" => raw_html_input_params}, socket) do
    changeset = validate_raw_html_input(raw_html_input_params, socket)
    case changeset.valid? do
      true ->
        {:noreply,
          socket
          |> assign(:raw_internal_tree,
            HtmlPreparations.convert_raw_html_input(raw_html_input_params["content"])
            |> InternalTree.garnish(%{})
            )
          |> assign(:step, :review_raw_internaltree)}
      false ->
        {:noreply, assign(socket, :changeset, changeset)}
    end
  end

  @impl true
  def handle_event("approve_raw_internaltree", _, socket) do
      socket = socket
      |> assign(:raw_internal_tree,
          InternalTree.partition_text(socket.assigns.raw_internal_tree)
          |> InternalTree.garnish(%{tunits: %{class: :tunit}})
          |> InternalTree.add_phx_click_event(
              nodes: :tunits,
              click: "toggle_selected_tunit")
        )
      |> assign(:menu_entries, InternalTree.tunit_modifiers())
    {:noreply, socket |> assign(:step, :review_translation_units)}
  end

  @impl true
  def handle_event("toggle_selected_tunit", %{"nid" => tunit_id}, socket) do
    {:noreply, toggle_selected_tunit(socket, tunit_id)}
  end

  defp toggle_selected_tunit(socket, tunit_id) do
    before = socket.assigns.selected_tunits
    selected_tunits = case Enum.member?(before, tunit_id) do
      false -> List.insert_at(before, -1, tunit_id)
      true -> List.delete(before, tunit_id)
    end
    fun = fn n -> n.nid in selected_tunits && "yes" || "no" end
    socket
    |> assign(:raw_internal_tree, InternalTree.garnish(socket.assigns.raw_internal_tree, %{tunits: %{selected: fun}}))
    |> assign(:selected_tunits, selected_tunits)
  end

  @impl true
  def handle_event("modify_tunits", %{"modifier" => modifier}, socket) do
    {:noreply,
      socket
      |> assign(:raw_internal_tree,
        InternalTree.modify_tunits(socket.assigns.raw_internal_tree, modifier, socket.assigns.selected_tunits)
      )}
  end

  @impl true
  def handle_event("approve_translation_units", _, socket) do
    {:noreply, socket |> assign(:step, :final_form)}
  end

  defp validate_raw_html_input(raw_html_input_params, socket) do
      socket.assigns.raw_html_input
      |> Articles.change_raw_html_input(raw_html_input_params)
      |> Map.put(:action, :validate)
  end
end
