import { Video, Layout, makeScene2D } from "@motion-canvas/2d";
import {
  Direction,
  all,
  beginSlide,
  createRef,
  slideTransition,
} from "@motion-canvas/core";
import { PEOPLE, Person, PersonI } from "../components/person";
import { birthdayCardFn, valentineCardFn } from "./generalized";
import { CardI } from "./birthday_letters";
import { FunctionBox } from "../components/function_box";
import curry from "../../public/img/curry.mp4";

export const cardGeneratorsFor = (
  person: PersonI,
): ((type: string) => () => CardI) => {
  const birthdayCardGenerator = () => birthdayCardFn(person);
  const valentineCardGenerator = () => valentineCardFn(person);

  const messageType = (type: string) => {
    switch (type) {
      case "valentine":
        return valentineCardGenerator;
      case "birthday":
        return birthdayCardGenerator;
    }
    throw new Error(type + " not implemented");
  };

  return messageType;
};

export const cardGeneratorsForSource = `const cardGeneratorsFor = (person: PersonI): ((type: string) => () => CardI) => {
  const birthdayCardGenerator = () => birthdayCardFn(person);
  const valentineCardGenerator = () => valentineCardFn(person);

  const generatorForType = (type: string) => {
    switch (type) {
      case "valentine":
        return valentineCardGenerator;
      case "birthday":
        return birthdayCardGenerator;
    }

    throw new Error(type + " not implemented");
  };

  return generatorForType;
};`;

export default makeScene2D(function* (view) {
  const box = createRef<FunctionBox>();
  const vid = createRef<Video>();

  view.add(
    <Layout>
      <FunctionBox
        ref={box}
        fn={cardGeneratorsFor}
        source={cardGeneratorsForSource}
        outputFontSize={20}
      />
      <Video ref={vid} src={curry} width={0} />
    </Layout>,
  );

  yield* all(
    box().reset(0.1),
    box().showCode(0.5),
    slideTransition(Direction.Left, 0.5),
  );

  yield* beginSlide("show code");

  const [alan] = PEOPLE;
  yield* box().setInputs([{ val: alan, node: <Person person={alan} /> }], 0.5);

  yield* beginSlide("show inputs");

  yield* box().hideCode(0.5);
  yield* box().propogateInput(0.5);
  yield* box().propogateOutput(0.5);

  yield* beginSlide("create child function");

  const child = box().getChild();
  yield* child().showCode(0.5);

  yield* beginSlide("show child function");

  yield* child().hideCode(0.5);
  yield* child().setInputs([{ val: "valentine" }], 0.5);
  yield* child().propogateInput(0.5);
  yield* child().propogateOutput(0.5);

  const curriedChild = child().getChild();
  yield* curriedChild().showCode(0.5);

  yield* beginSlide("propogate child function");

  yield* curriedChild().hideCode(0.5);
  yield* curriedChild().setInputs([{ val: "" }], 0.5);
  yield* curriedChild().propogateInput(0.5);
  yield* curriedChild().propogateOutput(0.5);

  yield* beginSlide("propogate curry");

  yield vid().play();
  yield vid().loop(true);
  yield* vid().width(400, 2);

  yield* beginSlide("do i smell curry");
});
