import React from "react";
import { TransitionProps } from "react-transition-group/Transition";
import { Transition } from "../_util/transition";
import { BaseTransition } from "../transition/BaseTransition";
import { hashObject } from "../_util/hash-object";
import { insertCSS } from "../_util/insert-css";

const rootId = "tea-notification-root";

export function getRoot(classPrefix: string) {
  let root: HTMLElement = window[rootId] || document.getElementById(rootId);
  if (!root) {
    root = document.createElement("div");
    root.id = rootId;
    root.className = `${classPrefix}-notification-wrap`;
    document.body.appendChild(root);
    window[rootId] = root;
  }
  return root;
}

const maxCountLimit = 3;
const listKey = "tea-notification-list-identification";

interface NoticeItem {
  hide: () => void;
  renew: () => void;
  show: () => void;
  isExisted: () => boolean;
  identifier: string;
}

export function limit(notice: NoticeItem) {
  if (!window[listKey]) {
    window[listKey] = [];
  }

  if (notice.identifier) {
    const existedItem = (window[listKey] as NoticeItem[]).find(
      i => i.isExisted && i.isExisted() && i.identifier === notice.identifier
    );
    // 存在相同内容，续期原内容
    if (existedItem) {
      existedItem.renew();
      return;
    }
    notice.show();
  } else {
    notice.show();
  }

  if (window[listKey].length >= maxCountLimit) {
    try {
      window[listKey][0].hide();
      window[listKey].shift();
    } catch (_) {
      // hide failed
    }
  }
  window[listKey].push(notice);
}

export interface NotificationTransitionProps extends Partial<TransitionProps> {
  /**
   * 动画元素目标高度
   */
  height?: number;
}

export function NotificationTransition(props: NotificationTransitionProps) {
  return <BaseTransition {...transition()} {...props} />;
}

const generateCSS = (transition: Transition, targetMaxHeight: number) => `
.${transition.classNames}-enter {
  opacity: 0 !important;
  transform: translate3d(60px, 0px, 0);
}
.${transition.classNames}-enter-active {
  opacity: 1 !important;
  transform: translate3d(0, 0, 0);
  transition: opacity ${transition.timeout.enter}ms ease,
    transform ${transition.timeout.enter}ms ease;
}
.${transition.classNames}-exit {
    opacity: 1;
    max-height: ${targetMaxHeight}px;
    margin-bottom: 20px;
}
.${transition.classNames}-exit-active {
    max-height: 0;
    margin-bottom: 0 !important;
    opacity: 0;
    transition: max-height ${transition.timeout.exit}ms ease,
      margin-bottom ${transition.timeout.exit}ms ease,
      opacity ${transition.timeout.enter}ms ease;
}
`;

const setupTransitions: { [hash: number]: Transition } = {};

export function transition(
  targetHeight = 150,
  enterTimeout = 300,
  leaveTimeout = 300
) {
  const name = `tea-transition-notification`;
  const hash = hashObject({ name, targetHeight, enterTimeout, leaveTimeout });

  if (!setupTransitions[hash]) {
    setupTransitions[hash] = {
      classNames: name + hash,
      timeout: {
        enter: enterTimeout,
        exit: leaveTimeout,
      },
      unmountOnExit: true,
      mountOnEnter: true,
    };
    const transition = setupTransitions[hash];
    const css = generateCSS(transition, targetHeight);
    insertCSS(name + hash, css);
  }

  return setupTransitions[hash];
}
