import React, { Component } from "react";
import { tBaseStore } from "../../store";
import ModalBase from "./ModalBase";
import { emptyFunc } from "./configs";
import { ModalPortalProps, ModalPortalState, ModalProps } from "./types";

let modal: ModalPortal;

export class ModalPortal extends Component<ModalPortalProps, ModalPortalState> {
  id = 0;

  constructor(props: ModalPortalProps) {
    super(props);
    this.id = 0;
    this.state = { stack: [] };
    modal = this as ModalPortal;
  }

  static get ref() {
    return modal;
  }

  static get size() {
    return modal.state.stack.length;
  }

  static show(children: any, props: ModalProps) {
    return modal.show({ children, ...props });
  }

  static update(key: string, props: ModalProps) {
    modal.update(key, props);
  }

  static dismiss(key: string) {
    modal.dismiss(key);
  }

  static dismissAll() {
    modal.dismissAll();
  }

  get current() {
    return this.state.stack.pop()?.key;
  }

  generateKey = () => {
    return `tlm-${this.id++}`;
  };

  getIndex = (key: string) => {
    return this.state.stack.findIndex((i) => i.key === key);
  };

  getProps = (props: ModalProps) => {
    const key = props.key || this.generateKey();
    return { visible: true, ...props, key };
  };

  show = (props: ModalProps) => {
    const mergedProps = this.getProps(props);
    this.setState(({ stack }) => {
      return { stack: stack.concat(mergedProps) };
    });
    return mergedProps.key;
  };

  update = (key: string, props: ModalProps) => {
    const mergedProps = this.getProps({ ...props, key });
    this.setState(({ stack }) => {
      const index = this.getIndex(key);
      stack[index] = { ...stack[index], ...mergedProps };
      return { stack };
    });
  };

  dismiss = (key = this.current) => {
    if (!key) return;
    const props = { ...this.state.stack[this.getIndex(key)], visible: false };
    this.update(key, props);
  };

  dismissAll = () => {
    this.state.stack.forEach(({ key }) => this.dismiss(key));
  };

  dismissHandler = (key: string) => {
    const { onClosed = emptyFunc } = this.state.stack[this.getIndex(key)] || {};
    this.setState(({ stack }) => {
      return { stack: stack.filter((i) => i.key !== key) };
    }, onClosed);
  };

  renderModal = ({ ...props }) => {
    return (
      <ModalBase
        {...props}
        key={props.key}
        onClosed={() => this.dismissHandler(props.key)}
      />
    );
  };

  render() {
    const { stack } = this.state;
    tBaseStore.setTotalModal(stack.length);
    tBaseStore.setAndroidInputMode(
      stack.length ? "resize" : tBaseStore.inputType
    );
    return stack.map(this.renderModal);
  }
}
