<script lang="ts">
  import { debounce, throttle } from "lodash";
  import Icon from "../../utils/Icon.svelte";
  import Spinner from "../../utils/Spinner.svelte";
  export let address: string;
  export let detail: boolean;

  enum State {
    LOADING = "loading",
    PREVIEW = "preview",
    PREVIEWING = "previewing",
    PLAYING = "playing",
    ERRORED = "errored",
  }
  let state = State.PREVIEW;

  let videoEl: HTMLVideoElement;

  const seek = throttle((progress: number) => {
    if (state === State.PREVIEWING) {
      videoEl.currentTime = videoEl.duration * progress;
    }
  }, 100);

  function updatePreviewPosition(ev: MouseEvent) {
    if (state === State.PREVIEW || state === State.PREVIEWING) {
      state = State.PREVIEWING;
      const bcr = videoEl.getBoundingClientRect();
      const progress = (ev.clientX - bcr.x) / bcr.width;
      seek(progress);
    }
  }

  function resetPreview() {
    if (state === State.PREVIEWING) {
      state = State.PREVIEW;
      videoEl.load();
    }
  }

  function startPlaying() {
    state = State.PLAYING;
    videoEl.play();
  }
</script>

<div class="video-viewer {state}">
  {#if state === State.LOADING}
    <Spinner />

    <img
      src="api/thumb/{address}"
      alt={address}
      on:load={() => (state = State.PREVIEW)}
      on:error={() => (state = State.ERRORED)}
    />
  {:else}
    <div class="player" style="--icon-size: {detail ? 100 : 32}px">
      <!-- svelte-ignore a11y-media-has-caption -->
      <video
        preload={detail ? "auto" : "metadata"}
        src="api/raw/{address}"
        poster="api/thumb/{address}"
        on:mousemove={updatePreviewPosition}
        on:mouseleave={resetPreview}
        on:click={startPlaying}
        controls={state === State.PLAYING}
        bind:this={videoEl}
      />
      <div class="play-icon">
        <div class="icon">
          <Icon plain name="play" />
        </div>
      </div>
    </div>
  {/if}
</div>

<style lang="scss">
  .video-viewer {
    video {
      width: 100%;
      max-height: 100%;

      background: rgba(128, 128, 128, 128);

      transition: filter 0.2s;
    }

    .player {
      position: relative;
    }

    .play-icon {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);

      $size: var(--icon-size);

      width: $size;
      height: $size;

      color: white;
      font-size: $size;
      line-height: 1;

      border-radius: calc($size / 4);
      border: .07em solid white;

      .icon {
        margin-left: .04em;
      }

      opacity: 0;
      transition: opacity 0.2s;

      pointer-events: none;
    }

    &.preview {
      video {
        filter: brightness(0.75);
      }
      .play-icon {
        opacity: 1;
      }
    }

    &.previewing video {
      cursor: pointer;
    }
  }
</style>
