import { apply, getType, getInst } from "dope2";
import type { Dynamic, State2Props } from "./util/extra";
import { Editor, type EditorState } from "./Editor";

import "./CallBlock.css";
import { useEffect } from "react";
import { Type } from "./Type";
import { Value } from "./Value";
import { focusPrevElement } from "./util/dom_trickery";

export interface CallBlockState {
  kind: "call";
  env: any;
  fn: EditorState;
  input: EditorState;
  resolved: undefined | Dynamic;
  rollback: EditorState;
}

interface CallBlockProps extends State2Props<CallBlockState> {
  onResolve: (resolved: EditorState) => void;
}

export function CallBlock({ state: {kind, env, fn, input, resolved, rollback }, setState, onResolve }: CallBlockProps) {
  const setResolved = (resolved?: Dynamic) => {
    setState({kind, env, fn, input, resolved, rollback});
  }

  const makeTheCall = (input, fn) => {
    console.log('makeTheCall...')
    try {
      const outputResolved = apply(input.resolved)(fn.resolved);
      setResolved(outputResolved);
      console.log("onResolve callblock..")
      onResolve({
        kind, env, fn, input, resolved: outputResolved, rollback
      });
    }
    catch (e) {
      console.log('makeTheCall:', e);
    }
  }

  const setFn = (fn: EditorState) => {
    setState({kind, env, fn, input, resolved, rollback});
  }
  const setInput = (input: EditorState) => {
    setState({kind, env, fn, input, resolved, rollback});
  }
  const onFnResolve = (fnState) => {
    console.log('my fn resolved')
    if (input.resolved) {
      makeTheCall(input, fnState);
    }
    else {
      // setFn(fnState);
      setResolved(undefined);
      onResolve({
        kind, env, fn: fnState, input, resolved: undefined, rollback
      });
    }
  }
  const onInputResolve = (inputState) => {
    console.log('my input resolved')
    if (fn.resolved) {
      makeTheCall(inputState, fn);
    }
    else {
      // setInput(inputState);
      setResolved(undefined);
      onResolve({
        kind, env, fn, input: inputState, resolved: undefined, rollback
      });
    }
  }
  const onFnCancel = () => {

  }
  const onInputCancel = () => {
    // we become what we were before we became a CallBlock
    if (rollback) {
      setState(rollback);
      focusPrevElement();
    }
  }

  return <span className="functionBlock">
    <div className="functionName">
    &#119891;&#119899;&nbsp;
      <Editor state={fn} setState={setFn}
        onResolve={onFnResolve} onCancel={onFnCancel}/>
    </div>
    <div className="functionParams">
      <div className="outputParam">
      <div className="inputParam">
        <Editor state={input} setState={setInput} onResolve={onInputResolve} onCancel={onInputCancel} />
      </div>
      { resolved
        ? <Value dynamic={resolved} />
        : <></> }
      </div>
    </div>
  </span>;
}
