import type { mastodon } from "masto";
import {
  type Component,
  For,
  createEffect,
  createRenderEffect,
  createSignal,
  onCleanup,
  onMount,
} from "solid-js";
import { css } from "solid-styled";
import tootStyle from "./toot.module.css";
import MediaViewer from "./MediaViewer";
import { render } from "solid-js/web";
import { useWindowSize } from "@solid-primitives/resize-observer";
import { useStore } from "@nanostores/solid";
import { $settings } from "../settings/stores";

const MediaAttachmentGrid: Component<{
  attachments: mastodon.v1.MediaAttachment[];
}> = (props) => {
  let rootRef: HTMLElement;
  const [viewerIndex, setViewerIndex] = createSignal<number>();
  const viewerOpened = () => typeof viewerIndex() !== "undefined";
  const windowSize = useWindowSize();
  const vh35 = () => Math.floor(windowSize.height * 0.35);
  const settings = useStore($settings);

  createRenderEffect((lastDispose?: () => void) => {
    lastDispose?.();
    const vidx = viewerIndex();
    if (typeof vidx === "undefined") return;
    const container = document.createElement("div");
    container.setAttribute("role", "presentation");
    document.body.appendChild(container);
    return render(() => {
      onCleanup(() => {
        document.body.removeChild(container);
      });

      return (
        <MediaViewer
          show={viewerOpened()}
          index={viewerIndex() || 0}
          onIndexUpdated={setViewerIndex}
          media={props.attachments}
          onClose={() => setViewerIndex()}
        />
      );
    }, container);
  });

  const openViewerFor = (index: number) => {
    setViewerIndex(index);
  };

  const columnCount = () => {
    if (props.attachments.length === 1) {
      return 1;
    } else if (props.attachments.length % 2 === 0) {
      return 2;
    } else {
      return 3;
    }
  };

  css`
    .attachments {
      column-count: ${columnCount.toString()};
    }
  `;
  return (
    <section
      ref={rootRef!}
      class={[tootStyle.tootAttachmentGrp, "attachments"].join(" ")}
      onClick={(e) => {
        if (e.target !== e.currentTarget) {
          e.stopImmediatePropagation();
        }
      }}
    >
      <For each={props.attachments}>
        {(item, index) => {
          const [loaded, setLoaded] = createSignal(false);
          const width = item.meta?.small?.width;
          const height = item.meta?.small?.height;
          const aspectRatio = item.meta?.small?.aspect;
          const maxHeight = vh35();
          const realHeight = height && height > maxHeight ? maxHeight : height;
          const realWidth =
            width && height && height > maxHeight
              ? maxHeight * (aspectRatio ?? 1)
              : width;
          const style = () =>
            loaded()
              ? undefined
              : {
                  width: realWidth ? `${realWidth}px` : undefined,
                  height: realHeight ? `${realHeight}px` : undefined,
                };
          switch (item.type) {
            case "image":
              return (
                <img
                  src={item.previewUrl}
                  style={style()}
                  alt={item.description || undefined}
                  onClick={[openViewerFor, index()]}
                  onLoad={[setLoaded, true]}
                  loading="lazy"
                ></img>
              );
            case "video":
              return (
                <video
                  src={item.url || undefined}
                  style={style()}
                  onLoadedMetadata={[setLoaded, true]}
                  autoplay={settings().autoPlayVideos}
                  playsinline={settings().autoPlayVideos ? true : undefined}
                  controls
                  poster={item.previewUrl}
                />
              );
            case "gifv":
              return (
                <video
                  src={item.url || undefined}
                  style={style()}
                  onLoadedMetadata={[setLoaded, true]}
                  autoplay={settings().autoPlayGIFs}
                  controls
                  playsinline /* or safari on iOS will play in full-screen */
                  loop
                  poster={item.previewUrl}
                />
              );

            case "audio":
            case "unknown":
              return <div></div>;
          }
        }}
      </For>
    </section>
  );
};

export default MediaAttachmentGrid;
