import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import {
  Balloon,
  BalloonDirection,
  BalloonSize,
  ButtonIcon,
  ButtonIconType,
  ButtonSize,
  Color,
  Layout,
  Interactable,
  StyledLayout,
  SVGAsset,
  Text,
} from 'twitch-core-ui';

import { ToggleBalloonWrapper } from 'mweb/common/components/more-ui/toggleBallonWrapper';
import {
  ChannelDetails,
  ChannelSubscribableStatus,
} from 'mweb/common/reducers/data/channels';
import {
  withTracking,
  TrackingProps,
  UITrackingParameters,
} from 'mweb/common/tracking/withTracking';
import { InteractionMedium } from 'mweb/common/tracking/extendInteractionMedium';

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

export const INTERACTION_MEDIUM_MENU = 'menu';
export const INTERACTION_CONTENT_MENU = 'menu';
export const INTERACTION_CONTENT_PRIVACY_POLICY = 'privacy_policy';
export const INTERACTION_CONTENT_COOKIE_POLICY = 'cookie_policy';
export const INTERACTION_CONTENT_TOS = 'terms_of_service';
export const INTERACTION_CONTENT_SWITCH_TO_DESKTOP = 'switch_to_desktop';
export const INTERACTION_CONTENT_SUBSCRIBE = 'subscribe';

export interface TopNavMenuProps extends TrackingProps {
  switchToDesktop: React.EventHandler<
    React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>
  >;
  currentChannel: ChannelDetails | undefined;
}

const IS_PRODUCTION = process.env.NODE_ENV === 'production';

export enum MenuItemType {
  Link = 'link',
  Separator = 'separator',
}

interface BaseMenuItemData {
  type: MenuItemType;
  hidden?: boolean;
}

interface MenuLinkData extends BaseMenuItemData {
  type: MenuItemType.Link;
  linkTo?: string;
  tracking?: UITrackingParameters;
  onClick?: React.EventHandler<
    React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>
  >;
  text: React.ReactNode;
  bold?: boolean;
}

interface MenuSeparatorData extends BaseMenuItemData {
  type: MenuItemType.Separator;
}

type MenuItemData = MenuLinkData | MenuSeparatorData;

export type MenuItemProps = MenuItemData & TrackingProps;

export class MenuItem extends React.PureComponent<MenuItemProps, {}> {
  get onClick():
    | React.EventHandler<React.MouseEvent<HTMLAnchorElement>>
    | undefined {
    if (this.props.type === MenuItemType.Separator) {
      return undefined;
    }

    return this.props.tracking
      ? this.props.trackClick(this.props.tracking, this.props.onClick)
      : this.props.onClick;
  }

  render(): JSX.Element | null {
    if (this.props.hidden) {
      return null;
    }

    if (this.props.type === MenuItemType.Separator) {
      return <StyledLayout margin={{ x: 1, y: 0.5 }} borderBottom />;
    }

    return (
      <Interactable linkTo={this.props.linkTo} onClick={this.onClick}>
        <StyledLayout padding={{ x: 1, y: 0.5 }} color={Color.Link}>
          <Text bold={this.props.bold}>{this.props.text}</Text>
        </StyledLayout>
      </Interactable>
    );
  }
}

const WrappedMenuItem = withTracking(MenuItem);

export function generateSubscriptionUrl(name: string): string {
  return `https://subs.twitch.tv/${name}`;
}

export class TopNavMenu extends React.PureComponent<TopNavMenuProps, {}> {
  get menuItems(): MenuItemData[] {
    return [
      {
        type: MenuItemType.Link,
        tracking: {
          interactionContent: INTERACTION_CONTENT_PRIVACY_POLICY,
        },
        linkTo: 'https://www.twitch.tv/p/privacy-policy',
        text: (
          <FormattedMessage
            id="cog-menu--privacy-policy"
            defaultMessage="Privacy Policy"
          />
        ),
      },
      {
        type: MenuItemType.Link,
        tracking: {
          interactionContent: INTERACTION_CONTENT_COOKIE_POLICY,
        },
        linkTo: 'https://www.twitch.tv/p/cookie-policy',
        text: (
          <FormattedMessage
            id="cog-menu--cookie-policy"
            defaultMessage="Cookie Policy"
          />
        ),
      },
      {
        type: MenuItemType.Link,
        tracking: {
          interactionContent: INTERACTION_CONTENT_TOS,
        },
        linkTo: 'https://www.twitch.tv/p/terms-of-service',
        text: (
          <FormattedMessage
            id="cog-menu--terms-of-service"
            defaultMessage="Terms of Service"
          />
        ),
      },
      {
        type: MenuItemType.Separator,
      },
      {
        type: MenuItemType.Link,
        tracking: {
          interactionContent: INTERACTION_CONTENT_SWITCH_TO_DESKTOP,
        },
        onClick: this.props.switchToDesktop,
        text: (
          <FormattedMessage
            id="switch-to-desktop--message"
            defaultMessage="Switch to Desktop Mode"
          />
        ),
        bold: true,
      },
      {
        type: MenuItemType.Link,
        tracking: {
          interactionContent: INTERACTION_CONTENT_SUBSCRIBE,
          interactionTargetPath:
            this.props.currentChannel &&
            `/subs/${this.props.currentChannel.name}`,
          interactionSubscribe: true,
        },
        linkTo:
          this.props.currentChannel &&
          generateSubscriptionUrl(this.props.currentChannel.name),
        hidden:
          !this.props.currentChannel ||
          this.props.currentChannel.subscribableStatus !==
            ChannelSubscribableStatus.CanSubscribe,
        text: this.props.currentChannel && (
          <FormattedMessage
            id="cog-menu--subscribe"
            defaultMessage={`Subscribe to {channel}`}
            values={{ channel: this.props.currentChannel.displayName }}
          />
        ),
        bold: true,
      },
      {
        type: MenuItemType.Separator,
        hidden: IS_PRODUCTION,
      },
      {
        type: MenuItemType.Link,
        linkTo: '//localhost.twitch.tv:3003/directory/all',
        text: 'All Channels Page',
        hidden: IS_PRODUCTION,
      },
      {
        type: MenuItemType.Link,
        linkTo: '//localhost.twitch.tv:3003/videos/137231756',
        text: 'VOD Page',
        hidden: IS_PRODUCTION,
      },
      {
        type: MenuItemType.Link,
        linkTo: '//localhost.twitch.tv:3003/bmkibler?stream_id=25794341392',
        text: 'LiveToVOD Demo',
        hidden: IS_PRODUCTION,
      },
      {
        type: MenuItemType.Link,
        linkTo: '//localhost.twitch.tv:3003/go/to/upsell',
        text: 'Upsell Page',
        hidden: IS_PRODUCTION,
      },
      {
        type: MenuItemType.Link,
        linkTo: '//localhost.twitch.tv:3003/events/268',
        text: 'Twitch Weekly Event',
        hidden: IS_PRODUCTION,
      },
      {
        type: MenuItemType.Link,
        linkTo: '//localhost.twitch.tv:3003/this/page/not/found',
        text: '404!',
        hidden: IS_PRODUCTION,
      },
      {
        type: MenuItemType.Link,
        linkTo: '//localhost.twitch.tv:3003/this/page/is/an/error',
        text: '500 =[',
        hidden: IS_PRODUCTION,
      },
      {
        type: MenuItemType.Link,
        linkTo: '//localhost.twitch.tv:3003/summit1g/rochat?theme=dark',
        text: 'Chat Embed',
        hidden: IS_PRODUCTION,
      },
    ];
  }

  render(): JSX.Element {
    return (
      <Layout className="mw-top-nav__menu">
        <ToggleBalloonWrapper>
          <ButtonIcon
            ariaLabel="Show top navigation menu"
            type={ButtonIconType.Primary}
            size={ButtonSize.Large}
            icon={SVGAsset.More}
            onClick={this.props.trackClick({
              interactionContent: INTERACTION_CONTENT_MENU,
            })}
          />
          <Balloon
            direction={BalloonDirection.BottomRight}
            size={BalloonSize.Small}
            noTail
          >
            <InteractionMedium medium={INTERACTION_MEDIUM_MENU}>
              <Layout padding={0.5}>
                {this.menuItems.map((item, idx) => (
                  <WrappedMenuItem key={idx} {...item} />
                ))}
              </Layout>
            </InteractionMedium>
          </Balloon>
        </ToggleBalloonWrapper>
      </Layout>
    );
  }
}

export default withTracking(TopNavMenu);
