<script>
  import DiscordReplay from "$/client/components/DiscordReplay.svelte";
  import HLSVideo from "$/client/components/HLSVideo.svelte";
  import WTVideo from "$/client/components/WTVideo.svelte";
  import Icon from "$/client/components/Icon.svelte";
  import IconImage from "$/client/components/IconImage.svelte";
  import Layout from '$/client/Layout.svelte';
  import Markdown from "$/client/components/Markdown.svelte";
  import parseISO from "date-fns/parseISO";
  import formatDistanceToNow from "date-fns/formatDistanceToNow";
  import { defer } from "$/client/helpers.js";
  import { onMount } from 'svelte';
  import Toasts from "$/client/components/Toasts.svelte";
  import SnapImage from "$/client/components/SnapImage.svelte";
  import { link } from "svelte-spa-router";
  import { load_past_streams, load_stream, change_stream } from "$/client/livestreams.js";
  import { user } from "$/client/stores.js";
  import { connect_socket, configure_socket } from "$/client/websocket.js";

  export let params = {};
  let livestream_id = params.livestream_id;
  const autoplay = true;
  let socket;
  let send_toast;
  let stream = {};

  let load_defer = defer();
  let past_defer = defer();

  const show_free_archived = (stream) => {
    return stream.state === "archived" && ($user.authenticated || stream.is_free);
  }

  const load_all = async () => {
    stream = await load_stream(livestream_id, false);

    load_defer.resolve(stream);

    if(stream.state === "live") {
      send_toast("Hit play if the video doesn't start.");
    }

    const past_streams = await load_past_streams();
    past_defer.resolve(past_streams);
  }

  const change_video_state = async () => {
    const status = await change_stream(livestream_id);

    if(status === 200) {
      stream = await load_stream(livestream_id, false);
      if(stream.state === "live") {
        send_toast("Stream is live!");
      }
    } else {
      send_toast("Request failed.");
    }
  }

  $: if(livestream_id !== params.livestream_id) {
    livestream_id = params.livestream_id;
    load_defer = defer();
    past_defer = defer();
    load_all();
  }


  onMount(async () => {
    await configure_socket();
    socket = connect_socket();

    socket.on("/live/update", async (data) => {
      if(data.message) send_toast(data.message);
      load_all();
    });

    await load_all();
  });
</script>

<style>

  container {
    display: flex;
    flex-direction: row;
    width: 100%;
  }

  container > left {
    width: 100%;
    max-height: calc(100vh - var(--fixed-header-height));
    overflow-y: auto;
    -ms-overflow-style: none;  /* IE and Edge */
    scrollbar-width: none;  /* Firefox */
    aspect-ratio: 16/9;
  }

  /* This combined with the -ms-overflow-style and scrollbar-width is how you remove
     the scrolls on the inner video/notes column.
   */
  container > left::-webkit-scrollbar {
    display: none;
  }

  container > left notes {
    display: flex;
    flex-direction: column;
    padding-left: 1rem;
    padding-right: 1rem;
  }

  container > waiting {
    display:flex;
    width: 100%;
    min-height: calc(100vh - var(--fixed-header-height));
    justify-content: center;
    align-items: center;
  }

  container > right {
    min-width: 400px;
    max-width: 400px;
    height: calc(100vh - var(--fixed-header-height));
    border-left: 1px solid var(--value7);
  }

  container > right.video-list {
    padding-left: 0.5rem;
    min-height: calc(100vh - var(--fixed-header-height));
    max-height: calc(100vh - var(--fixed-header-height));
    overflow-y: auto;
  }

  container > right card {
    border: unset;
    box-shadow: unset;
  }

  container > right card middle {
    margin-bottom: 0.3rem;
  }

  span#view-count {
    display: flex;
    align-content: center;
  }

  @media only screen and (max-width: 800px) {
    right {
      display: none;
    }
  }
</style>

<Layout centered={ true } fullwidth={ true } fixed={ true } footer={ false } auth_optional={ true } testid="live-page">
  <container>
  {#await load_defer}
    <br/>
  {:then}
      <left>
        {#if stream.state === "live"}
          <HLSVideo autoplay={ autoplay } poster={ stream.poster } source={ stream.source } />
        {:else if stream.state === "archived" }
          {#if show_free_archived(stream)}
            <WTVideo media={ stream.media } />
          {:else if stream.poster }
            <SnapImage src={ stream.poster } />
          {:else}
            <IconImage height="unset" aspect_ratio="16/9" name="film" />
          {/if}
        {:else if stream.state === "finished"}
          <IconImage height="unset" aspect_ratio="16/9" name="video-off" />
        {:else if stream.state === "pending"}
          <IconImage height="unset" aspect_ratio="16/9" name="clock" />
        {:else}
          <IconImage height="unset" aspect_ratio="16/9" name="video" />
        {/if}

        <info>
          <tile>
            <left>
              <Icon name="user" size="48" />
            </left>
            <middle>
              <b>Zed A. Shaw</b>
              <span>{ stream.title }</span>
            </middle>
            <right>

            {#if $user.admin}
              {#if stream.state === "live"}
                <span on:click={ () => change_video_state() }>
                  <Icon name="stop-circle" tip_position="bottom-left" tooltip="Stop stream." size="48" color="var(--red)"/>
                </span>
              {:else if stream.state === "pending"}
                <span on:click={ () => change_video_state() }>
                  <Icon name="arrow-up-circle" tip_position="bottom-left" tooltip="Announce ready." size="48" color="var(--yellow)"/>
                </span>
              {:else if stream.state === "ready"}
                <span on:click={ () => change_video_state() }>
                  <Icon name="cast" size="48" tip_position="bottom-left" tooltip="Go live." color="var(--green)"/>
                </span>
              {:else}
                <a use:link href="/admin/table/livestream/{ stream.id }/">Finished</a>
              {/if}
            {:else}
              <!--
              <span id="view-count">
                <Icon name="user" size="24" />&nbsp;{ stream.viewer_count }
                </span>
              -->
            {/if}
            </right>
          </tile>
        </info>

          <notes>
            <Markdown content={ stream.description } />
            <br>
            {#if stream.state === "pending"}
              <callout class="info">
              <span data-testid="pending-message">
                This live stream starts at <b>{ stream.starts_on }</b>.
                Come back then, and hit refresh.
              </span>
              </callout>
            {:else if stream.state === "ready"}
              <callout class="info">
              <span>
                The show is about to start.  Your page might refresh when it does, but if the video doesn't start on its own hit refresh.
              </span>
              </callout>
            {:else if stream.state === "finished"}
              <callout class="info">
              <span>
                This live stream has ended. It will be posted for later viewing after editing, probably in a few days.
              </span>
              </callout>
            {:else if stream.state === "archived"}
              <callout class="info">
              <span>
                {#if $user.authenticated}
                  I hope you enjoyed the stream. If you find a mistake or a problem with the video then please tell me in the chat.
                {:else if show_free_archived(stream) }
                  If you enjoyed this free livestream and would like to learn more JavaScript, then <a style="color: var(--value0)" href="/client/#/register/">register today</a> to get even more livestreams and an <b>entire course in JavaScript</b>.
                {:else}
                  This live stream is for members only.  If you want to learn JavaScript, then <a style="color: var(--value0)" href="/client/#/register/">register today</a> and enjoy all livestreams plus all modules.
                {/if}
              </span>
              </callout>
            {/if}
          </notes>
      </left>
      {#if ["pending", "finished", "archived"].includes(stream.state)}
        <right class="video-list">
          {#await past_defer then streams}
            {#each streams as archived}
              {#if archived.id !== stream.id}
              <card>
                <top>
                <a data-testid="past-link-{ archived.id }" use:link href="/live/{ archived.id }/">
                  {#if archived.poster}
                    <SnapImage src={ archived.poster } />
                  {:else}
                    <IconImage name="video" />
                  {/if}
                </a>
                </top>
                <middle>
                  <b>{ archived.title }</b>
                  <div>{ formatDistanceToNow(parseISO(archived.starts_on), {addSuffix: true}) }</div>
                </middle>
              </card>
              {/if}
            {/each}
          {/await}
        </right>
      {:else}
        <right>
          <DiscordReplay />
        </right>
      {/if}
    {/await}
  </container>

  <Toasts bind:send_toast fade_after={ 10000 } />
</Layout>
