import * as React from 'react';
import * as Cx from 'classnames';
import {
  defineMessages,
  injectIntl,
  InjectedIntl,
  FormattedMessage,
} from 'react-intl';
import {
  AlignItems,
  Background,
  ButtonIcon,
  ChannelStatusIndicatorStatus,
  ChannelStatusIndicator,
  Display,
  FlexWrap,
  JustifyContent,
  Layout,
  StyledLayout,
  InjectLayout,
  Stat,
  SVGAsset,
  Text,
  TextType,
} from 'twitch-core-ui';

import LatencyTrackedImage from 'mweb/common/latency/latencyTrackedImage';
import { ChannelOnlineStatus } from 'mweb/common/reducers/data/channels';
import {
  buildChannelPath,
  buildPathForBaseVideo,
} from 'mweb/common/utils/pathBuilders';
import { withTracking, TrackingProps } from 'mweb/common/tracking/withTracking';
import { extendInteractionMedium } from 'mweb/common/tracking/extendInteractionMedium';
import { TrackedLink } from 'mweb/common/tracking/trackedLink';
import { ClientOnly } from 'mweb/common/containers/clientOnly';
import VideoCard from 'mweb/common/components/videoCard';
import {
  VideoType,
  BaseVideoDetails,
} from 'mweb/common/reducers/data/baseVideoDetails';

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

const INTERACTION_MEDIUM = 'channel_info';
export const INTERACTION_CONTENT_LIVE_CHANNEL_LINK = 'live_channel_link';
export const INTERACTION_CONTENT_EXPAND = 'expand';
export const INTERACTION_CONTENT_MOST_POPULAR = 'most_popular_video';

const messages = defineMessages({
  followers: {
    id: 'followers',
    defaultMessage: 'Followers',
  },
  views: {
    id: 'views',
    defaultMessage: 'Views',
  },
});

interface ChannelInfoCardOwnProps {
  name: string;
  displayName: string | undefined;
  bannerImageURL: string | undefined;
  description: string | undefined;
  followerCount: number | undefined;
  lifetimeViewerCount: number | undefined;
  logoURL: string | undefined;
  onlineStatus: ChannelOnlineStatus | undefined;
  video: BaseVideoDetails | undefined;
}

export interface ChannelInfoCardProps
  extends ChannelInfoCardOwnProps,
    TrackingProps {
  intl: InjectedIntl;
}

interface ChannelInfoCardState {
  expanded: boolean;
}

export class ChannelInfoCardBase extends React.PureComponent<
  ChannelInfoCardProps,
  ChannelInfoCardState
> {
  state: ChannelInfoCardState = {
    expanded: false,
  };

  toggleDescription = (e: React.MouseEvent<HTMLButtonElement>) => {
    if (e && e.currentTarget) {
      e.currentTarget.blur();
    }
    this.setState((prevState: ChannelInfoCardState) => ({
      expanded: !prevState.expanded,
    }));
  };

  get channelName(): JSX.Element {
    const nameBase = (
      <Text type={TextType.H4} bold ellipsis>
        {this.props.displayName || this.props.name}
      </Text>
    );

    if (this.props.onlineStatus === ChannelOnlineStatus.Online) {
      return (
        <TrackedLink
          to={buildChannelPath(this.props.name)}
          interactionContent={INTERACTION_CONTENT_LIVE_CHANNEL_LINK}
        >
          <Layout
            display={Display.Flex}
            flexWrap={FlexWrap.NoWrap}
            justifyContent={JustifyContent.Start}
            alignItems={AlignItems.Center}
          >
            {nameBase}
            <Layout margin={{ left: 1, right: 0.5 }}>
              <ChannelStatusIndicator
                pulse={true}
                status={ChannelStatusIndicatorStatus.Live}
              />
            </Layout>
            <FormattedMessage id="channel-is-live" defaultMessage="LIVE" />
          </Layout>
        </TrackedLink>
      );
    }

    return nameBase;
  }

  get description(): JSX.Element | false {
    return (
      !!this.props.description && (
        <InjectLayout padding={{ x: 1, top: 0.5 }}>
          <Text>{this.props.description}</Text>
        </InjectLayout>
      )
    );
  }

  get mostPopular(): JSX.Element[] | undefined {
    if (!this.props.video) {
      return undefined;
    }
    const isClip = this.props.video.videoType === VideoType.Clip;
    return [
      <InjectLayout padding={{ x: 1, top: 1 }} key="video-header">
        <Text type={TextType.P} bold>
          {isClip ? (
            <FormattedMessage
              defaultMessage="Most Popular Clip"
              id="most-popular-clip"
            />
          ) : (
            <FormattedMessage
              defaultMessage="Most Popular Highlight"
              id="most-popular-highlight"
            />
          )}
        </Text>
      </InjectLayout>,
      <VideoCard
        key="video-card"
        title={this.props.video.title}
        imageURL={this.props.video.thumbnailURL}
        gameName={this.props.video.game}
        viewCount={this.props.video.viewCount}
        createdAt={this.props.video.date}
        formattedLength={this.props.video.formattedLength}
        borderTop={false}
        linkTo={buildPathForBaseVideo(this.props.video)}
        interactionContent={INTERACTION_CONTENT_MOST_POPULAR}
      />,
    ];
  }

  get expandedContent(): JSX.Element | undefined {
    return (
      <Layout
        className={Cx({
          'mw-channel-info-card__details': true,
          'mw-channel-info-card__details--visible': this.state.expanded,
        })}
      >
        {this.description}
        {this.mostPopular}
      </Layout>
    );
  }

  get viewerAndFollowerCounts(): JSX.Element[] | false {
    return (
      !!this.props.followerCount &&
      !!this.props.lifetimeViewerCount && [
        <Stat
          key="followers"
          icon={SVGAsset.GlyphFollowers}
          label={this.props.intl.formatMessage(messages.followers)}
          value={this.props.intl.formatNumber(this.props.followerCount, {
            maximumSignificantDigits: 3,
          })}
        />,
        <Text key="bullet" type={TextType.P} bold>
          &nbsp;&nbsp;&bull;&nbsp;&nbsp;
        </Text>,
        <Stat
          key="views"
          icon={SVGAsset.GlyphViews}
          label={this.props.intl.formatMessage(messages.views)}
          value={this.props.intl.formatNumber(this.props.lifetimeViewerCount, {
            maximumSignificantDigits: 3,
          })}
        />,
      ]
    );
  }

  render(): JSX.Element {
    return (
      <StyledLayout
        className="mw-channel-info-card"
        background={Background.Base}
        borderBottom
      >
        <div
          className="mw-channel-info-card__banner"
          style={{
            backgroundImage: `url(${this.props.bannerImageURL})`,
          }}
        />
        <Layout
          className="mw-channel-info-card__body"
          alignItems={AlignItems.Center}
          display={Display.Flex}
          flexWrap={FlexWrap.NoWrap}
          justifyContent={JustifyContent.Between}
          padding={{ x: 1, y: 0.5 }}
        >
          <StyledLayout className="mw-channel-info-card__avatar" elevation={2}>
            <LatencyTrackedImage
              className="mw-channel-info-card__avatar__image"
              alt={this.props.displayName || this.props.name}
              src={this.props.logoURL}
            />
          </StyledLayout>
          <Layout flexGrow={2} padding={{ x: 0.5 }}>
            {this.channelName}
            <Layout
              className="mw-channel-info-card__counts"
              display={Display.Flex}
              alignItems={AlignItems.Center}
              justifyContent={JustifyContent.Start}
            >
              {this.viewerAndFollowerCounts}
            </Layout>
          </Layout>
          <ClientOnly hasLatencyTrackedChildren>
            <ButtonIcon
              ariaLabel="Toggle channel description"
              icon={this.state.expanded ? SVGAsset.Close : SVGAsset.Plus}
              onClick={this.props.trackClick(
                {
                  interactionContent: INTERACTION_CONTENT_EXPAND,
                },
                this.toggleDescription,
              )}
            />
          </ClientOnly>
        </Layout>
        {this.expandedContent}
      </StyledLayout>
    );
  }
}

export const ChannelInfoCard = injectIntl(
  extendInteractionMedium(
    withTracking(ChannelInfoCardBase),
    INTERACTION_MEDIUM,
  ),
) as React.ComponentClass<ChannelInfoCardOwnProps>;
