// This program has been developed by students from the bachelor Computer Science at Utrecht
// University within the Software Project course.
// © Copyright Utrecht University (Department of Information and Computing Sciences)
import {useRef, useState} from "react";
import useFlowStore from "../VisProgStores.tsx";
import styles from './PlanEditor.module.css';
import { GetActionValue, type Action, type ActionTypes, type Plan } from "../components/Plan";
import { defaultPlan } from "../components/Plan.default";
import { TextField } from "../../../../components/TextField";
import GestureValueEditor from "./GestureValueEditor"; 

type PlanEditorDialogProps = {
  plan?: Plan;
  onSave: (plan: Plan | undefined) => void;
  description? : string;
};

export default function PlanEditorDialog({
  plan,
  onSave,
  description,
}: PlanEditorDialogProps) {
  // UseStates and references
  const dialogRef = useRef<HTMLDialogElement | null>(null);
  const [draftPlan, setDraftPlan] = useState<Plan | null>(null);
  const [newActionType, setNewActionType] = useState<ActionTypes>("speech");
  const [newActionGestureType, setNewActionGestureType] = useState<boolean>(true);
  const [newActionValue, setNewActionValue] = useState("");
  const [hasInteractedWithPlan, setHasInteractedWithPlan] = useState<boolean>(false)
  const { setScrollable } = useFlowStore();
  const nodes = useFlowStore().nodes;

  //Button Actions
  const openCreate = () => {
    setScrollable(false);
    setDraftPlan({...structuredClone(defaultPlan), id: crypto.randomUUID()});
    dialogRef.current?.showModal();
  };

  const openCreateWithDescription = () => {
    setScrollable(false);
    setDraftPlan({...structuredClone(defaultPlan), id: crypto.randomUUID(), name: description!});
    setNewActionType("llm")
    setNewActionValue(description!)
    dialogRef.current?.showModal();
  }

  const openEdit = () => {
    setScrollable(false);
    if (!plan) return;
    setDraftPlan(structuredClone(plan));
    dialogRef.current?.showModal();
  };

  const close = () => {
    setScrollable(true);
    dialogRef.current?.close();
    setDraftPlan(null);
  };

  const buildAction = (): Action => {
    const id = crypto.randomUUID();
    setHasInteractedWithPlan(true)
    switch (newActionType) {
    case "speech":
     return { id, text: newActionValue, type: "speech" };
    case "gesture":
        return { id, gesture: newActionValue, isTag: newActionGestureType, type: "gesture" };
    case "llm":
        return { id, goal: newActionValue, type: "llm" };
    }
  };

  return (<>
      {/* Create and edit buttons */}
      {!plan && (
          <button className={styles.nodeButton} onClick={description ? openCreateWithDescription : openCreate}>
          Create Plan
          </button>
      )}
      {plan && (
          <button className={styles.nodeButton} onClick={openEdit}>
          Edit Plan
          </button>
      )}

      {/* Start of dialog (plan editor) */}
      <dialog
        ref={dialogRef}
        className={`${styles.planDialog}`}
        //onWheel={(e) => e.stopPropagation()}
        data-testid={"PlanEditorDialogTestID"}
      >
      <form method="dialog" className="flex-col gap-md">
          <h3> {draftPlan?.id === plan?.id ? "Edit Plan" : "Create Plan"} </h3>
          {/* Plan name text field */}
          {draftPlan && (
              <TextField
                  value={draftPlan.name}
                  setValue={(name) =>
                  setDraftPlan({ ...draftPlan, name })}
              placeholder="Plan name"
              data-testid="name_text_field"/>
          )}

          {/* Entire "bottom" part (adder and steps) without cancel, confirm and reset */}
          {draftPlan && (<div className={styles.planEditor}>
              <div className={styles.planEditorLeft}>
              {/* Left Side (Action Adder) */}
                  <h4>Add Action</h4>
                  {(!plan && description && draftPlan.steps.length === 0 && !hasInteractedWithPlan) && (<div className={styles.stepSuggestion}>
                      <label> Filled in as a suggestion! </label>
                      <label> Feel free to change! </label>
                  </div>)}
                  <label>
                      Action Type <wbr />
                      {/* Type selection */}
                      <select
                          value={newActionType}
                          onChange={(e) => {
                              setNewActionType(e.target.value as ActionTypes);
                              // Reset value when action type changes
                              setNewActionValue("");
                          }}>
                      <option value="speech">Speech Action</option>
                      <option value="gesture">Gesture Action</option>
                      <option value="llm">LLM Action</option>
                      </select>
                  </label>

                  {/* Action value editor*/}
                  {newActionType === "gesture" ? (
                      // Gesture get their own editor component
                      <GestureValueEditor
                        value={newActionValue}
                        setValue={setNewActionValue}
                        setType={setNewActionGestureType}
                        placeholder="Gesture name"
                      />
                  ) : (
                      <TextField
                          value={newActionValue}
                          setValue={setNewActionValue}
                          placeholder={
                              newActionType === "speech" ? "Speech text"
                              : "LLM goal"
                          }
                      />
                  )}

                  {/* Adding steps */}
                  <button
                      type="button"
                      disabled={!newActionValue}
                      onClick={() => {
                          if (!draftPlan) return;
                          // Add action to steps
                          const action = buildAction();
                          setDraftPlan({
                              ...draftPlan,
                              steps: [...draftPlan.steps, action],});

                          // Reset current action building
                          setNewActionValue("");
                          setNewActionType("speech");
                      }}>
                  Add Step
                </button>
              </div>

              {/* Right Side (Steps shown) */}
              <div className={styles.planEditorRight}>
                  <h4>Steps</h4>

                  {/* Show if there are no steps yet */}
                  {draftPlan.steps.length === 0 && (
                      <div className={styles.emptySteps}>
                      No steps yet
                      </div>
                  )}


                  {/* Map over all steps */}
                  {draftPlan.steps.map((step, index) => (
                      <div
                      role="button"
                      tabIndex={0}
                      key={step.id}
                      className={styles.planStep}
                      // Extra logic for screen readers to access using keyboard
                      onKeyDown={(e) => {
                          if (e.key === "Enter" || e.key === " ") {
                          setDraftPlan({
                          ...draftPlan,
                          steps: draftPlan.steps.filter((s) => s.id !== step.id),});
                          }}}
                      onClick={() => {
                          setDraftPlan({
                          ...draftPlan,
                          steps: draftPlan.steps.filter((s) => s.id !== step.id),});
                      }}>

                      <span className={styles.stepIndex}>{index + 1}.</span>
                      <span className={styles.stepType}>{step.type}:</span>
                      <span className={styles.stepName}>
                        {
                        // This just tries to find the goals name, i know it looks ugly:(
                        step.type === "goal"
                        ? ((nodes.find(x => x.id === step.id)?.data.name as string) == "" ? 
                        "unnamed goal": (nodes.find(x => x.id === step.id)?.data.name as string))
                        : (GetActionValue(step) ?? "")}
                      </span>
                  </div>
                ))}
              </div>
            </div>
          )}

          {/* Buttons */}
          <div className="flex-row gap-md">
              {/* Close button */}
              <button type="button" onClick={close}>
              Cancel
              </button>

              {/* Confirm/ Create button */}
              <button
              type="button"
              disabled={!draftPlan}
              onClick={() => {
                  if (!draftPlan) return;
                  onSave(draftPlan);
                  close();
              }}>
              {draftPlan?.id === plan?.id ? "Confirm" : "Create"}
              </button>

              {/* Reset button */}
              <button
              type="button"
              disabled={!draftPlan}
              onClick={() => {
                  onSave(undefined);
                  close();
              }}>
              Reset
              </button>
        </div>
      </form>
    </dialog>
  </>
);
}