import * as React from 'react';

import Head from 'next/head';
import Link from 'next/link';
import { useRouter } from 'next/router';

import {
  Breadcrumb, Button, ButtonGroup, Col, Row,
} from 'react-bootstrap';

import { useIntl } from 'react-intl';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { GetServerSideProps, InferGetServerSidePropsType } from 'next';
import { IncomingMessage } from 'http';
import { VideoEntry } from 'util/datatypes/VideoList';
import DownloadButton from 'components/DownloadButton';
import { getHLSMasterURL } from '../../util';

import VideoPlayer from '../../components/VideoPlayer';
import CopyField from '../../components/CopyField';
import { FormattedMessage } from '../../components/localization';
import sanitizeFileName from '../../util/sanitizeFileName';
import sanitizeTitle from '../../util/sanitizeTitle';
import { notFound } from '../../util/status';
import { getIndex, getVideos } from '../../util/api';

export const getServerSideProps: GetServerSideProps = async (context) => {
  const { req }: { req: IncomingMessage } = context;
  const { id, vslug } = context.params || {};

  if (typeof id !== 'string') {
    throw new Error('only expected a single id');
  }

  if (typeof vslug !== 'string') {
    throw new Error('only expected a single vslug');
  }

  // Fetch URL to thumbnails server
  const {
    ids,
    servers: { hls: hlsServerURL, dash: dashServerURL },
  } = await getIndex();

  const vodMeta = ids.find(({
    id: thisID,
  }: {
    id: string
  }) => id === thisID);
  if (!vodMeta) {
    return { props: {} };
  }

  // Fetch list of videos for this VOD ID
  const vodInfo = await getVideos(id);
  let videos;
  if (Array.isArray(vodInfo)) {
    videos = vodInfo;
  } else {
    videos = vodInfo.videos;
  }

  // Check if vslug is actually an index number (old app style)
  /*
  NOTE - parseInt will accept strings CONTAINING numbers.
  This is supposed to reject strings that are not JUST numbers.
  */
  const vindexNum = +vslug;
  if (!Number.isNaN(vindexNum)) {
    // Check if video exists
    if (vindexNum < 0 || vindexNum >= videos.length) {
      return { props: {} };
    }
    const video = videos[vindexNum];
    return {
      props: {
        redirect: true,
        id,
        video,
        vslug: sanitizeTitle(video.title),
      },
    };
  }

  // Check if vslug is actually point to a file name
  const sanitizedFileName = sanitizeFileName(vslug);
  const realVIndex = videos.findIndex(
    (video: VideoEntry) => video.fileName === sanitizedFileName,
  );
  if (realVIndex >= 0) {
    const video = videos[realVIndex];
    return {
      props: {
        redirect: true,
        id,
        video: realVIndex,
        vslug: sanitizeTitle(video.title),
      },
    };
  }

  // Check if we can find any video with matching vslug
  const video = videos.find(({ title }: { title: string }) => sanitizeTitle(title) === vslug);
  if (!video) {
    return { props: {} };
  }

  // At this point we found the right video, just get more information at this point
  const { title } = vodMeta;

  // let basePath = null;
  // basePath = `${JSON.stringify(req.toString())}`;
  const basePath = `https://${req.headers.host}`;

  // Pass data to the page via props
  return {
    props: {
      id,
      vslug,
      video,
      title,
      hlsServerURL,
      dashServerURL,

      basePath,
    },
  };
};

export default function VideoPlayerPage({
  id,
  vslug,
  video,
  redirect,
  title,
  hlsServerURL,
  // dashServerURL,
  basePath,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
  if (redirect) {
    const router = useRouter();

    React.useEffect(() => {
      router.push(`/${id}/${vslug}`);
    });

    return (
      <p>
        You will be redirected
        {' '}
        <Link href="/[id]/[vslug]" as={`/${id}/${vslug}`}>
          <span>here</span>
        </Link>
        …
      </p>
    );
  }

  if (!video) {
    return notFound();
  }

  const intl = useIntl();

  const {
    fileName,
    title: videoTitle,
    sourceVideoURL,
    sourceVideoStart,
  } = video;

  return (
    <div>
      <Head>
        <title>
          {videoTitle}
          {' '}
          –
          {' '}
          {title}
          {' '}
          –
          {' '}
          {intl.formatMessage({
            id: 'App.title',
            description: 'The full title of the website',
            defaultMessage: 'Games Done Quick Instant Archive',
          })}
        </title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <Breadcrumb>
        <Link passHref href="/">
          <Breadcrumb.Item>
            <FormattedMessage
              id="Breadcrumb.homeTitle"
              defaultMessage="GDQ Instant Archive"
              description="Root node text in breadcrumb"
            />
          </Breadcrumb.Item>
        </Link>
        <Link passHref href="/[id]" as={`/${id}`}>
          <Breadcrumb.Item>{title}</Breadcrumb.Item>
        </Link>
        <Link passHref href="/[id]/[vslug]" as={`/${id}/${vslug}`}>
          <Breadcrumb.Item active>{videoTitle}</Breadcrumb.Item>
        </Link>
      </Breadcrumb>

      <VideoPlayer
        autoplay
        controls
        sources={[
          // getDASHManifestURL(dashServerURL, id, fileName),
          { src: getHLSMasterURL(hlsServerURL, id, fileName) },
        ]}
        aspectRatio="16:9"
        fill
      />

      <h1>
        {title}
        :
        {' '}
        {videoTitle}
      </h1>

      <Row className="mb-3">
        <Col sm={12} md={7}>
          <ButtonGroup>
            <DownloadButton id={id} fileName={fileName} />
            {sourceVideoURL ? (
              <Button
                href={
                  sourceVideoStart
                    ? `${sourceVideoURL}?t=${Math.floor(sourceVideoStart / 60)}m${sourceVideoStart % 60
                    }s`
                    : sourceVideoURL
                }
                target="blank"
                variant="twitch"
              >
                <FontAwesomeIcon icon={['fab', 'twitch']} className="mr-2" />
                <FormattedMessage
                  id="VideoPlayerPage.watchOnTwitch"
                  description="Button below video that links to the exact position in the archived stream to watch it there."
                  defaultMessage="Watch on Twitch"
                />
              </Button>
            ) : (
                ''
              )}
          </ButtonGroup>
        </Col>
        <Col sm={12} md={5}>
          <CopyField icon="share">
            {[basePath, id, vslug].join('/')}
          </CopyField>
        </Col>
      </Row>
    </div>
  );
}
