import expect from 'expect';
import {
  Layout,
  Animation,
  AnimationType,
  AnimationDuration,
  AnimationTiming,
  AnimationDelay,
  Toast,
} from 'twitch-core-ui';

import { partialPropShallowWrapper } from 'mtest/helpers/partialPropWrappers';

import { TimedToast, TimedToastProps } from 'src/common/components/timedToast';

describe('<TimedToast />', () => {
  const DEFAULT_PROPS: TimedToastProps = {
    secondsVisible: 10000,
  };

  const subject = partialPropShallowWrapper(TimedToast, DEFAULT_PROPS, {
    children: 'hello',
    disableLifecycleMethods: true,
  });

  it('renders nothing until marked ready', () => {
    expect(subject().find(Layout)).toNotExist();
  });

  it('has an animated toast with children inside', () => {
    const timedToast = subject();
    timedToast.setState({ readyForFirstRender: true });
    const toast = timedToast.find(Animation).find(Toast);
    expect(toast.children().text()).toBe('hello');
  });

  it('marks class timed-toast-bottom only if attached to bottom', () => {
    const timedToast = subject();
    timedToast.setState({ readyForFirstRender: true, enabled: true });
    expect(timedToast.find('.timed-toast-bottom')).toNotExist();

    const timedToastBottom = subject({ attachBottom: true });
    timedToastBottom.setState({ readyForFirstRender: true, enabled: true });
    expect(timedToastBottom.find('.timed-toast-bottom')).toExist();
  });

  describe('animation configuration', () => {
    it('is appropriate when toast is enabled', () => {
      const timedToast = subject();
      timedToast.setState({ readyForFirstRender: true, enabled: true });
      const animation = timedToast.find(Animation);
      expect(animation).toHaveProps({
        enabled: true,
        duration: AnimationDuration.Long,
        timing: AnimationTiming.EaseIn,
        delay: AnimationDelay.Long,
        type: AnimationType.SlideInTop,
      });
    });

    it('is appropriate when toast is enabled and disabled', () => {
      const timedToast = subject();
      timedToast.setState({ readyForFirstRender: true, enabled: true });

      let animation = timedToast.find(Animation);
      expect(animation).toHaveProps({
        enabled: true,
        duration: AnimationDuration.Long,
        timing: AnimationTiming.EaseIn,
        delay: AnimationDelay.Long,
        type: AnimationType.SlideInTop,
      });
      timedToast.setState({ enabled: false });

      animation = timedToast.find(Animation);
      expect(animation).toHaveProps({
        enabled: true,
        duration: AnimationDuration.Medium,
        timing: AnimationTiming.EaseIn,
        delay: AnimationDelay.Short,
        type: AnimationType.SlideOutTop,
      });
    });

    it('is appropriate when toast is attached to bottom', () => {
      const timedToast = subject({ attachBottom: true });
      timedToast.setState({ readyForFirstRender: true, enabled: true });

      let animation = timedToast.find(Animation);
      expect(animation).toHaveProps({
        enabled: true,
        duration: AnimationDuration.Long,
        timing: AnimationTiming.EaseIn,
        delay: AnimationDelay.Long,
        type: AnimationType.SlideInBottom,
      });
      timedToast.setState({ enabled: false });

      animation = timedToast.find(Animation);
      expect(animation).toHaveProps({
        enabled: true,
        duration: AnimationDuration.Medium,
        timing: AnimationTiming.EaseIn,
        delay: AnimationDelay.Short,
        type: AnimationType.SlideOutBottom,
      });
    });
  });

  describe('state enabled becomes false', () => {
    it('when close is called', () => {
      const toast = subject();
      expect(toast.state('enabled')).toEqual(false);
      toast.setState({ enabled: true });

      (toast.instance() as TimedToast).clickClose(undefined as any);

      expect(toast).toHaveState({ enabled: false });
    });

    it('when the hide timer expires', () => {
      const toast = partialPropShallowWrapper(TimedToast, {
        secondsVisible: 0.01,
      })();

      toast.setState({ readyForFirstRender: true, enabled: true });
      expect(toast).toHaveState({ enabled: true });

      return new Promise(resolve => {
        setTimeout(() => {
          expect(toast).toHaveState({
            enabled: false,
            readyForFirstRender: true,
          });
          resolve();
        }, 100);
      });
    });
  });
});
