import * as React from 'react';
import { FormattedMessage, defineMessages } from 'react-intl';
import {
  AlignItems,
  Button,
  ButtonType,
  Display,
  JustifyContent,
  Layout,
  Text,
  TextType,
} from 'twitch-core-ui';

import {
  BaseVideoDetails,
  VideoType,
} from 'mweb/common/reducers/data/baseVideoDetails';
import { ClipDetails } from 'mweb/common/reducers/data/clips';
import { VODDetails } from 'mweb/common/reducers/data/vods';
import { buildPathForBaseVideo } from 'mweb/common/utils/pathBuilders';
import { withTracking, TrackingProps } from 'mweb/common/tracking/withTracking';
import { extendInteractionMedium } from 'mweb/common/tracking/extendInteractionMedium';
import { asListItem } from 'mweb/common/components/asListItem';
import VideoCard from 'mweb/common/components/videoCard';
import { ClientOnly } from 'mweb/common/containers/clientOnly';

if (process.env.BROWSER) {
  require('./channelProfileVideoList.sass');
}

export const INTERACTION_CONTENT_SHOW_MORE = 'show_more';

const messages = defineMessages({
  headerArchives: {
    id: 'channel-profile-past-broadcasts',
    defaultMessage: "{channel}'s Past Broadcasts",
  },
  headerClips: {
    id: 'channel-profile-clips',
    defaultMessage: "{channel}'s Top Clips",
  },
  headerHighlights: {
    id: 'channel-profile-highlights',
    defaultMessage: "{channel}'s Recent Highlights",
  },
  headerVideos: {
    id: 'channel-profile-videos',
    defaultMessage: "{channel}'s Recent Videos",
  },
});

interface ChannelProfileVideoListBaseProps extends TrackingProps {
  videos: BaseVideoDetails[];
  channel: string;
}

interface ChannelProfileVideoListVODProps
  extends ChannelProfileVideoListBaseProps {
  videos: VODDetails[];
  type: VideoType.Archive | VideoType.Highlight | undefined;
}

interface ChannelProfileVideoListClipProps
  extends ChannelProfileVideoListBaseProps {
  videos: ClipDetails[];
  type: VideoType.Clip;
}

export type ChannelProfileVideoListProps =
  | ChannelProfileVideoListVODProps
  | ChannelProfileVideoListClipProps;

interface ChannelProfileVideoListState {
  expanded: boolean;
}

const VideoListItem = asListItem(VideoCard);

export class ChannelProfileVideoListBase extends React.Component<
  ChannelProfileVideoListProps,
  ChannelProfileVideoListState
> {
  state: ChannelProfileVideoListState = {
    expanded: false,
  };

  get headerTextIdAndDefault(): { id: string; defaultMessage: string } {
    switch (this.props.type) {
      case VideoType.Clip:
        return messages.headerClips;
      case VideoType.Highlight:
        return messages.headerHighlights;
      case VideoType.Archive:
        return messages.headerArchives;
      default:
        return messages.headerVideos;
    }
  }

  get videos(): BaseVideoDetails[] {
    return this.state.expanded
      ? this.props.videos
      : this.props.videos.slice(0, 3);
  }

  get isExpandable(): boolean {
    return !this.state.expanded && this.props.videos.length > 3;
  }

  get showMore(): JSX.Element {
    return (
      <Layout
        className="mw_channel_profile_video_list__show_more"
        display={Display.Flex}
        alignItems={AlignItems.Center}
        justifyContent={JustifyContent.Center}
      >
        <Button
          type={ButtonType.Text}
          onClick={this.props.trackClick(
            {
              interactionContent: INTERACTION_CONTENT_SHOW_MORE,
            },
            this.expand,
          )}
          dropdown
        >
          <Text type={TextType.H5}>
            <FormattedMessage id="show-more" defaultMessage="Show more" />
          </Text>
        </Button>
      </Layout>
    );
  }

  expand = (e: React.MouseEvent<HTMLButtonElement>) => {
    if (e && e.currentTarget) {
      e.currentTarget.blur();
    }
    this.setState(() => ({ expanded: true }));
  };

  render(): JSX.Element {
    return (
      <Layout
        className="mw-channel-profile-video-list"
        padding={{ bottom: !this.isExpandable ? 3 : 0 }}
        fullWidth
      >
        <Layout padding={{ x: 1, y: 0.5 }}>
          <Text type={TextType.H5}>
            <FormattedMessage
              {...this.headerTextIdAndDefault}
              values={{ channel: this.props.channel }}
            />
          </Text>
        </Layout>
        <Layout>
          {this.videos.map((video, idx) => (
            <VideoListItem
              key={video.id}
              title={video.title}
              imageURL={video.thumbnailURL}
              gameName={video.game}
              viewCount={video.viewCount}
              createdAt={video.date}
              formattedLength={video.formattedLength}
              borderTop={!idx}
              linkTo={buildPathForBaseVideo(video)}
              position={idx}
            />
          ))}
        </Layout>
        <ClientOnly serverHeight={this.isExpandable ? '5rem' : undefined}>
          {this.isExpandable && this.showMore}
        </ClientOnly>
      </Layout>
    );
  }
}

function interactionMedium(props: ChannelProfileVideoListProps): string {
  return `${props.type || 'video'}_list`;
}

export const ChannelProfileVideoList = extendInteractionMedium(
  withTracking(ChannelProfileVideoListBase),
  interactionMedium,
);
