<script lang="ts" context="module">
  export enum VideoScrollDirection {
    RIGHT = "right",
    LEFT = "left",
    UP = "up",
    DOWN = "down",
  }

  export interface VideoScrollDef {
    id: string;
    top: number;
    left: number;
    angle: number;
    width: number;
    height: number;
    directions: VideoScrollDirection[];
    files: string[];
  }
</script>

<script lang="ts">
  import { rotate } from "../utils";
  import { onMount } from "svelte";

  export let definition: VideoScrollDef;

  let root: HTMLDivElement;
  let dynamicFiles: { id: string; top: number; left: number; src: string }[] =
    [];
  $: {
    dynamicFiles = definition.files.slice(1).map((src: string, idx: number) => {
      const id = `${idx}_${src}`;
      const cy =
        definition.top +
        (isVertical ? definition.height * (idx + 1) * verticalDirection : 0);
      const cx =
        definition.left +
        (isHorizontal ? definition.width * (idx + 1) * horizontalDirection : 0);
      const [left, top] = rotate(
        cx,
        cy,
        definition.left,
        definition.top,
        definition.angle
      );
      return { id, top, left, src };
    });
  }

  $: isHorizontal = definition.directions.some(
    (dir: VideoScrollDirection) =>
      dir === VideoScrollDirection.LEFT || dir === VideoScrollDirection.RIGHT
  );
  $: isVertical = definition.directions.some(
    (dir: VideoScrollDirection) =>
      dir === VideoScrollDirection.UP || dir === VideoScrollDirection.DOWN
  );
  $: horizontalDirection = definition.directions.includes(
    VideoScrollDirection.RIGHT
  )
    ? 1
    : -1;
  $: verticalDirection = definition.directions.includes(
    VideoScrollDirection.DOWN
  )
    ? 1
    : -1;

  onMount(() => {
    const observer = new IntersectionObserver((entries, _) => {
      entries.forEach((entry) => {
        const element = entry.target as HTMLImageElement;
        if (entry.isIntersecting) {
          element.classList.add("visible");
          if (!element.src) {
            console.debug(
              `[VIDEOSCROLL] Intersected, loading ${element.dataset.src}`
            );
            element.src = element.dataset.src!;
            setTimeout(() => {
              element.classList.add("displayed");
            }, 3000);
            element.onload = () => {
              element.classList.add("displayed");
              element.classList.add("loaded");
              if (isHorizontal) {
                element.style.height = "auto";
              } else {
                element.style.width = "auto";
              }
            };
          }
        }
      });
    });
    if (root) {
      Array.from(root.children).forEach((el) => {
        observer.observe(el);
      });
    }
  });
</script>

{#if definition.directions.length > 0}
  <div class="video-scroll" bind:this={root}>
    <img
      class="visible displayed loaded"
      src={definition.files[0]}
      style:top="{Math.round(definition.top)}px"
      style:left="{Math.round(definition.left)}px"
      style:width={isHorizontal ? `${Math.round(definition.width)}px` : "auto"}
      style:height={isVertical ? `${Math.round(definition.height)}px` : "auto"}
      style:transform="rotate({definition.angle}deg)"
      alt=""
    />

    {#each dynamicFiles as file (file.id)}
      <img
        data-src={file.src}
        style:top="{Math.round(file.top)}px"
        style:left="{Math.round(file.left)}px"
        style:width="{Math.round(definition.width)}px"
        style:height="{Math.round(definition.height)}px"
        style:transform="rotate({definition.angle}deg)"
        alt=""
      />
    {/each}
  </div>
{/if}

<style lang="scss">
  .video-scroll img {
    position: absolute;
    image-rendering: optimizeSpeed;
    background: grey;
    visibility: hidden;
    opacity: 0;
    transition: opacity 0.5s;

    &.visible {
      visibility: visible !important;
    }

    &.displayed {
      opacity: 1 !important;
    }

    &.loaded {
      background: transparent !important;
    }
  }
</style>
