import * as React from 'react';
import {
  Layout,
  Animation,
  ZIndex,
  AnimationType,
  AnimationDuration,
  AnimationTiming,
  AnimationDelay,
  Toast,
  Position,
  AlignItems,
  Display,
} from 'twitch-core-ui';

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

export interface TimedToastProps {
  secondsVisible: number;
  secondsDelayUntilVisible?: number;
  onClickClose?: React.MouseEventHandler<HTMLElement>;
  attachBottom?: boolean;
}

interface TimedToastState {
  enabled: boolean;
  readyForFirstRender: boolean;
}

export class TimedToast extends React.PureComponent<
  TimedToastProps,
  TimedToastState
> {
  state: TimedToastState = {
    enabled: false,
    readyForFirstRender: false,
  };

  private showTimerHandle: number | undefined = undefined;
  private hideTimerHandle: number | undefined = undefined;

  componentDidMount(): void {
    this.showTimerHandle = window.setTimeout(() => {
      this.showToastAndStartHideTimer();
    }, (this.props.secondsDelayUntilVisible || 0) * 1000);
  }

  componentWillUnmount(): void {
    this.clearTimers();
  }

  clickClose = (e: React.MouseEvent<HTMLButtonElement>) => {
    if (e && e.currentTarget) {
      e.currentTarget.blur();
    }
    if (this.props.onClickClose) {
      this.props.onClickClose(e);
    }
    this.setState(() => ({ enabled: false }));
    this.clearTimers();
  };

  render(): JSX.Element | false {
    return (
      this.state.readyForFirstRender && (
        <Layout
          alignItems={AlignItems.Center}
          zIndex={ZIndex.Default}
          position={Position.Fixed}
          attachBottom={this.props.attachBottom}
          fullWidth
        >
          <Animation
            type={this.animationType}
            duration={
              this.state.enabled
                ? AnimationDuration.Long
                : AnimationDuration.Medium
            }
            timing={AnimationTiming.EaseIn}
            delay={
              this.state.enabled ? AnimationDelay.Long : AnimationDelay.Short
            }
            enabled
          >
            {/* This works because the flex stylings override the width of the toast.*/}
            {/* If toast attached to bottom, add shadow to top with css since core-ui elevation applies only to bottom */}
            <Layout
              fullWidth
              flexGrow={1}
              display={Display.Flex}
              className={this.props.attachBottom ? 'timed-toast-bottom' : ''}
            >
              <Toast onClose={this.clickClose}>{this.props.children}</Toast>
            </Layout>
          </Animation>
        </Layout>
      )
    );
  }

  private get animationType(): AnimationType {
    if (this.props.attachBottom) {
      return this.state.enabled
        ? AnimationType.SlideInBottom
        : AnimationType.SlideOutBottom;
    } else {
      return this.state.enabled
        ? AnimationType.SlideInTop
        : AnimationType.SlideOutTop;
    }
  }

  private showToastAndStartHideTimer(): void {
    this.setState(() => ({ readyForFirstRender: true, enabled: true }));
    this.hideTimerHandle = window.setTimeout(() => {
      this.setState(() => ({ enabled: false }));
    }, this.props.secondsVisible * 1000);
  }

  private clearTimers(): void {
    if (this.showTimerHandle) {
      clearTimeout(this.showTimerHandle);
    }
    if (this.hideTimerHandle) {
      clearTimeout(this.hideTimerHandle);
    }
  }
}
