import { useContext } from "react";

import { EnvContext } from "../../context/EnvContext";
import { GlobalContext } from "../../context/GlobalContext";
import { type TypeInfoLet } from "../../eval/infer_type";
import { Input } from "../other/Input";
import { Type, TypeInfoBlock } from "../other/Type";
import { ExprBlock, type ExprBlockState, type State2Props } from "./ExprBlock";

import "./LetInBlock.css";

export interface LetInBlockState {
  kind: "let";
  name: string;
  focus: boolean;
  value: ExprBlockState;
  inner: ExprBlockState;
}

export interface LetInBlockProps extends State2Props<LetInBlockState,ExprBlockState> {
  typeInfo: TypeInfoLet;
}

export function LetInBlock(props: LetInBlockProps) {
  return <span className="letIn">
    <div className="decl">
      <DeclColumns {...props} />
    </div>
    <div className="inner">
      <InnerMost {...props} />
    </div>
  </span>
}

function DeclColumns({state, setState, score, typeInfo}) {
  const globalContext = useContext(GlobalContext);

  const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
  const setValue = callback => setState(state => ({...state, value: callback(state.value)}));

  return <>
    <span className="keyword column">let&nbsp;</span>
      <span className="column rightAlign">
        <Input
          placeholder="<name>"
          text={state.name}
          suggestion=""
          onEnter={() => {}}
          onCancel={() => {}}
          onTextChange={name => setState(state => ({...state, name}))}
          extraHandlers={{}}
          />
        <br/>
        :: <TypeInfoBlock typeInfo={typeInfo.value} />
      </span>
      <span className="keyword column">&nbsp;=&nbsp;</span>
      <span className="column">
        <ExprBlock
          state={state.value}
          setState={setValue}
          score={suggestion => score({ ...state, value: suggestion })}
          onCancel={() => setState(state => state.inner)} // keep inner
          typeInfo={typeInfo.value}
          />
      </span>
    {state.inner.kind === "let" &&
     globalContext?.syntacticSugar &&
      <EnvContext value={typeInfo.innerEnv}>
        <DeclColumns
          state={state.inner}
          setState={setInner}
          score={suggestion => score({ ...state, inner: suggestion })}
          typeInfo={typeInfo.inner}
          />
      </EnvContext>
    }
  </>;
}

function InnerMost({state, setState, score, typeInfo}) {
  const globalContext = useContext(GlobalContext);
  const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
  const onCancel = () => setState(state => state.value);
  if (state.inner.kind === "let" && globalContext?.syntacticSugar) {
    return <EnvContext value={typeInfo.innerEnv}>
        <InnerMost
          state={state.inner}
          setState={setInner}
          score={suggestion => score({ ...state, inner: suggestion })}
          typeInfo={typeInfo.inner}
          />
      </EnvContext>;
  }
  else {
    return <EnvContext value={typeInfo.innerEnv}>
      <ExprBlock
        state={state.inner}
        setState={setInner}
        score={suggestion => score({ ...state, inner: suggestion })}
        onCancel={onCancel} // keep value
        typeInfo={typeInfo.inner}
        />
    </EnvContext>
  }
}