// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import type { AttachmentType } from '../types/Attachment';
import {
  hasFailed,
  hasNotResolved,
  isDownloaded,
  isGIF,
  isVideo,
} from '../types/Attachment';
import { count } from './grapheme';
import { SECOND } from './durations';

const DEFAULT_DURATION = 5 * SECOND;
const MAX_VIDEO_DURATION = 30 * SECOND;

export async function getStoryDuration(
  attachment: AttachmentType
): Promise<number | undefined> {
  if (hasFailed(attachment)) {
    return DEFAULT_DURATION;
  }

  if (attachment.textAttachment) {
    // Minimum 5 seconds. +1 second for every 15 characters past the first
    // 15 characters (round up).
    // For text stories that include a link, +2 seconds to the playback time.
    const length = attachment.textAttachment.text
      ? count(attachment.textAttachment.text)
      : 0;
    const additionalSeconds = (Math.ceil(length / 15) - 1) * SECOND;
    const linkPreviewSeconds = attachment.textAttachment.preview
      ? 2 * SECOND
      : 0;
    return DEFAULT_DURATION + additionalSeconds + linkPreviewSeconds;
  }

  if (!isDownloaded(attachment) || hasNotResolved(attachment)) {
    return;
  }

  if (isGIF([attachment]) || isVideo([attachment])) {
    const videoEl = document.createElement('video');
    if (!attachment.url) {
      return DEFAULT_DURATION;
    }
    videoEl.src = attachment.url;

    await new Promise<void>(resolve => {
      function resolveAndRemove() {
        resolve();
        videoEl.removeEventListener('loadedmetadata', resolveAndRemove);
      }

      videoEl.addEventListener('loadedmetadata', resolveAndRemove);
    });

    const duration = Math.ceil(videoEl.duration * SECOND);

    if (isGIF([attachment])) {
      // GIFs: Loop gifs 3 times or play for 5 seconds, whichever is longer.
      return Math.min(
        Math.max(duration * 3, DEFAULT_DURATION),
        MAX_VIDEO_DURATION
      );
    }

    // Video max duration: 30 seconds
    return Math.min(duration, MAX_VIDEO_DURATION);
  }

  if (attachment.caption) {
    const length = count(attachment.caption);
    const additionalSeconds = (Math.ceil(length / 15) - 1) * SECOND;
    return DEFAULT_DURATION + additionalSeconds;
  }

  return DEFAULT_DURATION;
}
