/*
  interface idea 2:
  - We want to let engineers use container queries for minor responsive stuff.
  - We also want to provide distinct evos for different use cases
  - We would like to be able to whitelist or blacklist evos to (for example) force the full-page content to appear when the pokemon is a page, even if the page is very small.
    - This implies that all evos need to be able to handle a full range of sizes!

  So perhaps, what we're after is a a way to say "show the best of this set of evos here" and have the app bake in some expand-to-next-evo buttons?

  Or... better yet, the eng passes in a function to decide which evo to display given available context.


  <Pokemon selectEvo={(width, height, role) => {
    if (role === 'page') {
      return Venusaur;
    }

    if (width < 100) return Bulbasaur;
    if (width < 200) return Ivysaur;
    return Venusaur;
  }} />
*/
import styled from '@emotion/styled';
import React, { useEffect, useMemo, useRef, useState } from 'react';

import { Slot, useLayoutSlotContext } from './slotSystem';

const PokemonContainer = styled.div`
  container-type: size;
  container-name: pokemon;
  width: 100%;
  height: 100%;
`;

function PokemonSizer<EvoProps extends object>({
  selectEvo,
  evoProps,
}: {
  selectEvo: (
    width: number,
    height: number,
    mode: string
  ) => React.ComponentType<EvoProps>;
  evoProps: EvoProps;
}) {
  const [size, setSize] = useState<{ w: number; h: number }>({
    w: Infinity,
    h: Infinity,
  });

  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (ref.current) {
      const container = ref.current;
      const observer = new ResizeObserver((entries) => {
        const size = entries[0].contentBoxSize[0];
        setSize({ w: size.inlineSize, h: size.blockSize });
      });
      observer.observe(container);
      return () => {
        observer.unobserve(container);
        observer.disconnect();
      };
    }
  }, [ref]);

  const { mode } = useLayoutSlotContext({});

  const Evo = useMemo(
    () => selectEvo(size.w, size.h, mode),
    [selectEvo, size.w, size.h, mode]
  );

  return (
    <PokemonContainer ref={ref}>
      <Evo {...evoProps} />
    </PokemonContainer>
  );
}

export default function PokemonV2<EvoProps extends object>({
  selectEvo,
  evoProps,
}: {
  selectEvo: (
    width: number,
    height: number,
    mode: string
  ) => React.ComponentType<EvoProps>;
  evoProps: EvoProps;
}) {
  return (
    <Slot>
      <PokemonSizer selectEvo={selectEvo} evoProps={evoProps} />
    </Slot>
  );
}
