<script lang="ts">
  /* eslint svelte/no-at-html-tags: "off" */

  import settings from '$stores/settings';
  import type { Media } from '$lib/Data/AniList/media';
  import { cleanCache, incrementMediaProgress } from '$lib/Media/Anime/cache';
  import { totalEpisodes } from '$lib/Media/Anime/episodes';
  import type { AniListAuthorisation } from '$lib/Data/AniList/identity';
  import ListTitle from '../ListTitle.svelte';
  import { onDestroy, onMount } from 'svelte';
  import AiringTime from '$lib/Media/Anime/Airing/AiringTime.svelte';
  import { browser } from '$app/environment';
  import identity from '$stores/identity';
  import '../covers.css';
  import revalidateAnime from '$stores/revalidateAnime';
  import CleanGrid from '$lib/List/CleanGrid.svelte';
  import CleanList from '../CleanList.svelte';

  export let media: Media[];
  export let title: any;
  export let animeLists: Promise<Media[]>;
  export let user: AniListAuthorisation;
  export let endTime: number;
  export let lastUpdatedMedia: number;
  export let completed = false;
  export let previousAnimeList: Media[];
  export let pendingUpdate: number | null;
  export let upcoming = false;
  export let notYetReleased = false;
  export let dummy = false;

  let keyCacher: NodeJS.Timeout;
  let totalEpisodeDueCount = media
    .map((anime) => {
      if ($settings.displayTotalEpisodes && anime.status === 'FINISHED')
        return anime.episodes - (anime.mediaListEntry?.progress || 0);

      if (anime.status === 'NOT_YET_RELEASED') return 1;

      return (
        (anime.nextAiringEpisode?.episode || 1) -
        (anime.mediaListEntry?.progress || 0) -
        (upcoming || notYetReleased ? 0 : 1)
      );
    })
    .reduce((a, b) => a + b, 0);

  onMount(() => {
    if (dummy) return;

    keyCacher = setInterval(
      () => {
        media = media;

        if (
          media.some(
            (m) => m.nextAiringEpisode?.airingAt && m.nextAiringEpisode.airingAt < Date.now() / 1000
          )
        )
          animeLists = cleanCache(user, $identity);
      },
      (() => {
        const airingAt = media
          .filter(
            (m) =>
              (m.status === 'RELEASING' || m.status === 'NOT_YET_RELEASED') &&
              m.nextAiringEpisode?.airingAt
          )
          .find((m) => m.nextAiringEpisode?.airingAt)?.nextAiringEpisode?.airingAt;
        const untilAiring = airingAt
          ? Math.round((airingAt - Date.now() / 1000) * 100) / 100
          : undefined;

        return untilAiring ? (untilAiring < 0 ? 1000 : untilAiring) : 1000;
      })()
    );

    if (browser)
      localStorage.setItem(
        `last${
          notYetReleased ? 'NotYetReleased' : upcoming ? 'Upcoming' : completed ? 'Completed' : ''
        }AnimeListLength`,
        media.length.toString()
      );
  });

  onDestroy(() => clearInterval(keyCacher));

  const increment = (anime: Media, progress: number) => {
    if (!dummy && pendingUpdate !== anime.id) {
      $revalidateAnime = true;
      lastUpdatedMedia = anime.id;
      pendingUpdate = anime.id;

      incrementMediaProgress(anime.id, anime.mediaListEntry?.progress, user, () => {
        const mediaListEntry = media.find((m) => m.id === anime.id)?.mediaListEntry;

        if (mediaListEntry) mediaListEntry.progress = progress + 1;

        previousAnimeList = media;
        animeLists = cleanCache(user, $identity);
        pendingUpdate = null;
      });
    }
  };
</script>

<ListTitle
  time={endTime / 1000}
  count={$settings.displayTotalDueEpisodes || $settings.displayTotalEpisodes
    ? totalEpisodeDueCount
    : media.length}
  {title}
  hideTime={dummy}
  hideCount={dummy}
/>

{#if media.length === 0}
  No anime to display. <button on:click={() => (animeLists = cleanCache(user, $identity))}>
    Force refresh
  </button>
{/if}

{#if $settings.displayCoverModeAnime}
  <CleanGrid {media} {dummy} type="anime" {upcoming} {notYetReleased}>
    <div slot="title" let:title={anime} let:progress>
      {#if !upcoming && !notYetReleased}
        {pendingUpdate === anime.id ? progress + 1 : progress}{@html totalEpisodes(anime)}
        <button
          class={`button-square button-action ${pendingUpdate === anime.id ? 'opaque' : ''}`}
          style={pendingUpdate === anime.id ? 'pointer-events: none;' : ''}
          on:click={() => increment(anime, progress)}>+</button
        >
        {#if !completed || dummy}
          [{anime.nextAiringEpisode?.episode === -1
            ? '?'
            : (anime.nextAiringEpisode?.episode || 1) - 1}]
          <br />
          <AiringTime originalAnime={anime} />
        {/if}
      {:else}
        <AiringTime originalAnime={anime} upcoming={true} />
      {/if}
    </div>
  </CleanGrid>
{:else}
  <CleanList {media} type="anime" {upcoming} {notYetReleased} {lastUpdatedMedia}>
    <span slot="information" let:title={anime} let:progress>
      {#if !upcoming || notYetReleased || !$settings.displayCountdownRightAligned}
        <span class="opaque">|</span>
      {/if}
      {#if !upcoming || notYetReleased}
        <!-- {anime.mediaListEntry?.progress || 0}{@html totalEpisodes(anime)} -->
        {pendingUpdate === anime.id ? progress + 1 : progress}{@html totalEpisodes(anime)}
        <button
          class={`button-square button-action ${pendingUpdate === anime.id ? 'opaque' : ''}`}
          style={pendingUpdate === anime.id ? 'pointer-events: none;' : ''}
          on:click={() => increment(anime, progress)}>+</button
        >
        {#if !completed}
          [{anime.nextAiringEpisode?.episode === -1
            ? '?'
            : (anime.nextAiringEpisode?.episode || 1) - 1}]
          <span class:countdown={$settings.displayCountdownRightAligned}>
            <AiringTime originalAnime={anime} />
          </span>
        {/if}
      {:else}
        <span class:countdown={$settings.displayCountdownRightAligned}>
          <AiringTime originalAnime={anime} upcoming={true} />
        </span>
      {/if}
    </span>
  </CleanList>
{/if}
