import {
  Img,
  Rect,
  Node,
  Video,
  makeScene2D,
  Txt,
  Line,
  LineSegment,
} from "@motion-canvas/2d";
import {
  Direction,
  beginSlide,
  createRef,
  map,
  slideTransition,
  tween,
  all,
  waitFor,
} from "@motion-canvas/core";

import { CodeBlock } from "@motion-canvas/2d/lib/components/CodeBlock";
import { theme } from "../theme";

const fibonacciFn = (n: number): number => {
  if (n <= 2) {
    return 1;
  }
  return fibonacciFn(n - 1) + fibonacciFn(n - 2);
};

const fibonacci = `
const fibonacci = (n: number): number => {
  if (n <= 2) {
    return 1;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
};
`
  .split("\n")
  .filter((x) => x.trim())
  .join("\n");

export default makeScene2D(function* (view) {
  const block = createRef<CodeBlock>();
  const node = createRef<Node>();
  const rect = createRef<Rect>();

  const boxMoji = createRef<Txt>();
  const inSegment = createRef<Line>();
  const outSegment = createRef<Line>();
  const input = createRef<Txt>();
  const output = createRef<Txt>();

  yield* view.add(
    <>
      <Rect
        ref={rect}
        radius={4}
        stroke={theme.overlay0.hex}
        fill={theme.crust.hex}
        lineWidth={4}
        padding={60}
        layout
      >
        <Node ref={node} opacity={0}>
          <CodeBlock
            fontFamily={theme.font}
            language="typescript"
            ref={block}
            fontSize={1}
            code={fibonacci}
          ></CodeBlock>
        </Node>
      </Rect>
      <Txt fontFamily={theme.font} fill={theme.text.hex} ref={boxMoji}>
        😴
      </Txt>
      <Line
        points={[]}
        ref={inSegment}
        stroke={theme.green.hex}
        lineWidth={8}
        radius={40}
        endArrow
      ></Line>
      <Line
        points={[]}
        ref={outSegment}
        stroke={theme.red.hex}
        lineWidth={8}
        radius={40}
        endArrow
      ></Line>
      <Txt
        opacity={0}
        fontFamily={theme.font}
        fill={theme.text.hex}
        ref={input}
      ></Txt>
      <Txt
        opacity={0}
        fontFamily={theme.font}
        fill={theme.text.hex}
        ref={output}
      ></Txt>
    </>,
  );

  yield boxMoji().position(rect().middle());
  yield* slideTransition(Direction.Left);

  yield* beginSlide("Black Box");

  const padding = 100;
  const left = rect().left();
  const right = rect().right();
  yield* all(
    inSegment().points([left.addX(-padding), left], 0.5),
    outSegment().points([right, right.addX(padding)], 0.5),
  );
  yield input().position(left.addX(-padding));
  yield output().position(right);
  for (const i of [1, 2, 3]) {
    yield* all(
      input().opacity(1, 0.5),
      input().text(i.toString(), 0.5),
      input().position(left.addX(-padding - 20), 0.5),
    );

    yield* beginSlide("Input " + i);

    yield* input().position(left, 0.5);
    yield* all(input().opacity(0, 0.2), boxMoji().text("👷‍♀️⚙️", 0.2));
    yield* waitFor(0.5);

    const result = fibonacciFn(i);
    yield* all(
      output().opacity(1, 0.5),
      output().text(result.toString(), 0.5),
      output().position(right, 0.5),
    );

    yield* all(boxMoji().text("😴", 0.2));

    yield* beginSlide("Output " + i);
  }

  yield* all(
    boxMoji().opacity(0, 0.2),
    block().fontSize(30, 1),
    node().opacity(1, 1),
  );

  yield* beginSlide("Revealing");
});
