import { useContext } from "react";

import { ExprBlock, type ExprBlockState } from "./ExprBlock";
import { EnvContext } from "./EnvContext";
// import { evalExprBlock, makeInnerEnv, scoreResolved, type ResolvedType } from "./eval";
import { type State2Props } from "./ExprBlock";
import { GlobalContext } from "./GlobalContext";

import "./LetInBlock.css";
import { Input } from "./Input";
import { inferTypeLet } from "./infer_type";
import { Type } from "./Type";

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

export interface LetInBlockProps extends State2Props<LetInBlockState,ExprBlockState> {
}

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}) {
  const env = useContext(EnvContext);
  const globalContext = useContext(GlobalContext);

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

  // const valueSuggestionPriority = (suggestion: ResolvedType) => {
  //   const innerEnv = makeInnerEnv(env, name, suggestion);
  //   const [resolved] = evalExprBlock(inner, innerEnv);
  //   return scoreResolved(resolved, score);
  // };

  // const [valueResolved] = evalExprBlock(value, env);
  // const innerEnv = makeInnerEnv(env, name, valueResolved);

  const {paramType, innerEnv} = inferTypeLet(state, env);

  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={{}}
          />
        :: <Type type={paramType} />
      </span>
      <span className="keyword column">&nbsp;=&nbsp;</span>
      <span className="column">
        <ExprBlock
          state={state.value}
          setState={setValue}
          score={() => 0}
          onCancel={() => setState(state => state.inner)} // keep inner
          />
      </span>
    {state.inner.kind === "let" &&
     globalContext?.syntacticSugar &&
      <EnvContext value={innerEnv}>
        <DeclColumns
          state={state.inner}
          setState={setInner}
          score={score}
          />
      </EnvContext>
    }
  </>;
}

function InnerMost({state, setState, score}) {
  const env = useContext(EnvContext);
  const globalContext = useContext(GlobalContext);
  const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
  // const [valueResolved] = evalExprBlock(state.value, env);
  // const innerEnv = makeInnerEnv(env, state.name, valueResolved);
  const {paramType, innerEnv} = inferTypeLet(state, env);
  const onCancel = () => setState(state => state.value);
  if (state.inner.kind === "let" && globalContext?.syntacticSugar) {
    return <EnvContext value={innerEnv}>
        <InnerMost
          state={state.inner}
          setState={setInner}
          score={score}
          />
      </EnvContext>;
  }
  else {
    return <EnvContext value={innerEnv}>
      <ExprBlock
        state={state.inner}
        setState={setInner}
        score={score}
        onCancel={onCancel} // keep value
        />
    </EnvContext>
  }
}