import { fetchGQL } from 'mweb/common/fetch/fetchGQL';
import {
  ChannelGQL,
  mapChannelGQLtoChannelDetails,
} from 'mweb/common/fetch/channels';
import {
  EventModel,
  EventType,
  PremiereEventModel,
  PremiereStatus,
  DEFAULT_EVENT_COVER_IMAGE_URL_TEMPLATE,
} from 'mweb/common/reducers/data/events';
import { logger } from 'tachyon-logger';
import { VODDetails } from 'mweb/common/reducers/data/vods';
import { VideoGQL, mapVideoGQLToVODDetails } from 'mweb/common/fetch/vods';
import { GameGQL, parseGameGQL } from 'mweb/common/fetch/games';
import { GameDetails } from 'mweb/common/reducers/data/games';
import { ChannelDetails } from 'mweb/common/reducers/data/channels';

const CoreChannelFragment: string = require('mweb/common/fetch/fragments/coreChannel');
const StreamFragment: string = require('mweb/common/fetch/fragments/stream');
const GameFragment: string = require('mweb/common/fetch/fragments/game');
const VideoFragment: string = require('mweb/common/fetch/fragments/video');
const EventQuery: string = require('mweb/common/fetch/queries/event');

interface PremiereGQL {
  id: string;
  status: PremiereStatus;
  pastPremiere?: VideoGQL;
}

export interface EventGQL {
  id: string;
  __typename: string;
  startAt: string;
  endAt: string;
  imageURL: string;
  description: string;
  title: string;
  channel: ChannelGQL;
  game?: GameGQL;
  premiere?: PremiereGQL;
}

export interface FetchEventGQL {
  data: {
    event: EventGQL | null;
  };
}

export interface EventDataPayload {
  event: EventModel;
  channel: ChannelDetails;
  game: GameDetails | undefined;
  vod: VODDetails | undefined;
}

export function compileFetchEventsOperation(): string {
  return `${EventQuery}
    ${CoreChannelFragment}
    ${StreamFragment}
    ${GameFragment}
    ${VideoFragment}
  `;
}

export async function fetchEvent(
  eventID: string,
): Promise<EventDataPayload | null> {
  const eventGQL = await fetchGQL<FetchEventGQL>(
    compileFetchEventsOperation(),
    {
      eventID,
    },
    'EventQuery',
  );
  return parseEventGQL(eventGQL);
}

export function parseEventGQL({
  data: { event },
}: FetchEventGQL): EventDataPayload | null {
  if (!event || !event.id) {
    return null;
  }
  const eventDetails = mapEventToEventModel(event);
  const channelDetails = mapChannelGQLtoChannelDetails(event.channel);
  if (!eventDetails || !channelDetails) {
    return null;
  }

  return {
    event: eventDetails,
    channel: channelDetails,
    game: event.game && parseGameGQL(event.game),
    vod:
      event.premiere &&
      event.premiere.pastPremiere &&
      mapVideoGQLToVODDetails(event.premiere.pastPremiere),
  };
}

export function mapEventToEventModel(event: EventGQL): EventModel | null {
  if (!(event.__typename in EventType)) {
    logger.warn([
      'mapEventToEventDetails called with unknown typename',
      event.__typename,
    ]);
    return null;
  }

  if (event.__typename === EventType.PremiereEvent && event.premiere) {
    return {
      id: event.id,
      type: EventType.PremiereEvent,
      startTime: new Date(event.startAt).valueOf(),
      endTime: new Date(event.endAt).valueOf(),
      coverImageTemplateURL:
        event.imageURL || DEFAULT_EVENT_COVER_IMAGE_URL_TEMPLATE,
      description: event.description,
      title: event.title,
      channel: event.channel.login || '',
      game: event.game && event.game.name,
      premiere: {
        id: event.premiere.id,
        status: event.premiere.status,
        vodID: event.premiere.pastPremiere && event.premiere.pastPremiere.id,
      },
    } as PremiereEventModel;
  }
  return {
    type: EventType.SingleEvent,
    id: event.id,
    startTime: new Date(event.startAt).valueOf(),
    endTime: new Date(event.endAt).valueOf(),
    coverImageTemplateURL:
      event.imageURL || DEFAULT_EVENT_COVER_IMAGE_URL_TEMPLATE,
    description: event.description,
    title: event.title,
    channel: event.channel.login || '',
    game: event.game && event.game.name,
  };
}
