import { createSignal } from "solid-js";
import { Digith } from "src/ui/Digith";
import { useProgram } from "src/ui/ProgramProvider";
import { CodeEditor } from "src/ui/Component/CodeEditor";
import { sourceText } from "src/lang/parser/source_text";
import { Program } from "src/lang/program";
import { V, Validation, letValidate } from "src/ui/validation";
import { validateNameRaw, validateSignalExprRaw } from "src/ui/validation/helpers";
import { DigithError } from "src/ui/Digith/DigithError";
import { spawnSignalDigith } from "src/ui/Scrowl/scrowlStore";

type Input = {
  raw_name: string,
  raw_body: string,
}

const validator: Validation<Input, Program.CreateSignal, DigithError> = letValidate(
  (input) =>({
    name: V.elseErr(validateNameRaw(input.raw_name), err =>({
      payload: { tag: "Parse", err, src: sourceText(input.raw_name) },
      ids: ["name"],
      tags: ["footer"],
      config: { title: "Signal Name", display: "flat" },
    })),
    body: V.elseErr(validateSignalExprRaw(input.raw_body), err => ({
      payload: { tag: "Parse", err, src: sourceText(input.raw_body) },
      ids: ["body"],
      tags: ["footer"],
      config: { title: "Signal Body", display: "flat" },
    })),
  }),
  (fields, input) => {
    const createSignal: Program.CreateSignal = {
      name: fields.name,
      body: fields.body,
      raw_body: input.raw_body,
    };

    return V.ok(createSignal);
})


export function NewSignalDraftDigith(props: { draft: Digith.NewSignalDraft }) {
  const program = useProgram();

  const [name, setName] = createSignal(props.draft.raw_name);
  const [body, setBody] = createSignal(props.draft.raw_body);

  const [errors, setErrors] = createSignal<DigithError[]>([]);

  function handleCommit() {
    setErrors([]);
    const validRes = validator({ raw_name: name(), raw_body: body() });
    if (validRes.tag === "errors") {
      setErrors(validRes.errors);
      return;
    }
    const createSignal = validRes.value;

    const programRes = Program.registerSignal(program, createSignal);
    if (programRes.tag === "error") {
      setErrors([{
        payload: { tag: "Program", err: programRes.error },
        ids: ["program"],
        tags: ["footer"],
        config: { title: "Registration Failed" },
      }]);
      return;
    }
    const signalName = programRes.value;

    spawnSignalDigith(program, signalName, props.draft.id);
  };

  return (
    <article>
      <header><strong>Signal (Draft)</strong></header>

      <div class="grid">
        <label>
          Name
          <input 
            type="text" 
            placeholder="my_sig" 
            value={name()} 
            onInput={(e) => setName(e.currentTarget.value)} 
          />
        </label>
      </div>

      <label>Body</label>
      <CodeEditor 
        value={body()} 
        onUpdate={setBody} 
        onRun={handleCommit} 
      />

      <footer>
        <button class="primary" onClick={handleCommit}>Commit</button>
      </footer>

      <div style={{ "margin-top": "1rem" }}>
        <DigithError.ByTag errors={errors()} tag="footer" />
      </div>
    </article>
  );
}
