import React from 'react';
 
import focusTrap from './Modal.FocusTrap';

let listOfWrapperElementsToFloatingUI = [];
let pageElementReference;
let isKeyDownEventListenerConfigured = false;

export default class Modal extends React.Component {
  constructor(props) {
    super(props);
    // Create a div that we'll render the modal into. Because each
    // Modal component has its own element, we can render multiple
    // modal components into the modal container.
    
    this.el = document.createElement('div');
   // this.el = props.modalContainerNode;
    this.el.className = 'floatingcontainer_' + new Date().getTime();
    this.renderProps = {};
    
    
    this.bindKeyDownEventToDocument =
      this.bindKeyDownEventToDocument.bind(this);
    this.handleKeyPressEvent = this.handleKeyPressEvent.bind(this);
    this.checkStatusOfKeyDownEventBoundToDocument = this.checkStatusOfKeyDownEventBoundToDocument.bind(this);
    this.setKeyDownEventBoundToDocumentStatusToTrue = this.setKeyDownEventBoundToDocumentStatusToTrue.bind(this);
  }

  componentDidMount() {
    this.props.modalrootNode.appendChild(this.el);

    this.mapFloatingContainerWithDIalogElement();
    this.applyFocusToFloatingDialogElement(this.el.className);
    this.persistPageElementReference();
    this.bindKeyDownEventToDocument();
  }

  mapFloatingContainerWithDIalogElement() {
    listOfWrapperElementsToFloatingUI.push({
      [this.el.className]: {
        modalroot: this.props.modalrootNode,
        floatinguicontainerelement: this.el,
        functionReferenceToFocus: this.props.focusDialogReference ?this.props.focusDialogReference :false,
        functionReferenceToClose: this.props.closeDialogReference,
        isOverlayNeeded: !!this.props.freezeLayer
      }
    });
  }


  applyFocusToFloatingDialogElement(refClass) {
    let indexOfContainerElement = this.getIndexOfContainerElement(refClass);
    let floatingContainerObj =
      listOfWrapperElementsToFloatingUI[indexOfContainerElement][refClass];
    floatingContainerObj.functionReferenceToFocus && floatingContainerObj.functionReferenceToFocus();
  }

  
  bindKeyDownEventToDocument() {
    if (!this.checkStatusOfKeyDownEventBoundToDocument()) {
      document.addEventListener('keydown', this.handleKeyPressEvent, true);
      this.setKeyDownEventBoundToDocumentStatusToTrue();
    
    }
  }
  checkStatusOfKeyDownEventBoundToDocument() {
    return isKeyDownEventListenerConfigured;
  }
  setKeyDownEventBoundToDocumentStatusToTrue() {
    isKeyDownEventListenerConfigured = true;
  }
  handleKeyPressEvent(event) {
    if (event.eventPhase === 3) {
      return false;
    }
    if (event.key === 'Escape' && this.props.isCloseOnEscapeNeeded) {
            
        let floatingDialogContinerClassName =
          this.getClassNameOfClosestContainerElement(event.target);
          let indexOfContainerElement =    floatingDialogContinerClassName === undefined ?  listOfWrapperElementsToFloatingUI.length-1 :this.getIndexOfContainerElement(
            floatingDialogContinerClassName );
          if (floatingDialogContinerClassName === undefined )
          {
            floatingDialogContinerClassName = this.getClassNameOfContainerElement(indexOfContainerElement);
          }
        
          this.invokeCloseCallBackFunctionOfDialogElement(
            indexOfContainerElement,
            floatingDialogContinerClassName
          );
          
        }
     else if (event.key === 'Tab' ) {
       this.isTabKeyPressed = true;
      let floatingDialogContinerClassName =
        this.getClassNameOfClosestContainerElement(event.target);
      if (floatingDialogContinerClassName !== undefined) {
        let indexOfContainerElement = this.getIndexOfContainerElement(
          floatingDialogContinerClassName
        );
        if(this.props.isTrapFocusNeeded)
        {
          focusTrap(event,listOfWrapperElementsToFloatingUI[indexOfContainerElement][
            floatingDialogContinerClassName
          ].floatinguicontainerelement );     
        }
      }
    }
  }
  getClassNameOfClosestContainerElement(elemObj) {
    if (elemObj.closest('div[class^=floatingcontainer_]') !== null) {
      return elemObj.closest('div[class^=floatingcontainer_]').className;
    }
  }

  getClassNameOfContainerElement(index) {
    let containerObj = listOfWrapperElementsToFloatingUI[index];
    return Object.keys(containerObj)[0];
  }

  getContainerElement(index) {
    let containerObj = listOfWrapperElementsToFloatingUI[index];
    return containerObj[Object.keys(containerObj)[0]];
  }

  getIndexOfContainerElement(valueToMatch) {
    let that = this;
    return listOfWrapperElementsToFloatingUI.findIndex(function (element) {
      return that.findIndexOfContainerElement(element, valueToMatch);
    });
  }
  findIndexOfContainerElement(element, floatingDialogContinerClassName) {
    return Object.keys(element)[0] == floatingDialogContinerClassName;
  }

  removeFloatingUIContainerElement(index, refClass) {
    if (Object.keys(listOfWrapperElementsToFloatingUI[index])[0] === refClass) {
      let floatingContainerObj =
        listOfWrapperElementsToFloatingUI[index][refClass];

      let floatingContainerElem =
        floatingContainerObj.floatinguicontainerelement;

      let modalRoot = floatingContainerObj.modalroot;
      modalRoot.removeChild(floatingContainerElem);
      listOfWrapperElementsToFloatingUI.splice(index, 1);

      if (listOfWrapperElementsToFloatingUI.length === 0) {
        this.resetModalBoxValues();
      } else {
        let topElem = this.getContainerElement(
          listOfWrapperElementsToFloatingUI.length - 1
        );
       topElem.functionReferenceToFocus && topElem.functionReferenceToFocus();
      }
    }
  }

  invokeCloseCallBackFunctionOfDialogElement(indexOfDialogElement, refClass) {
    listOfWrapperElementsToFloatingUI[indexOfDialogElement][
      refClass
    ].functionReferenceToClose();
  }

  getTopMostFloatingUIContainerElement(refClass) {
    let lengthOfUIContainerElement = listOfWrapperElementsToFloatingUI.length;

    return listOfWrapperElementsToFloatingUI[lengthOfUIContainerElement - 1][
      refClass
    ].floatinguicontainerelement;
  }
  getFloatingUIContainerElement(index, refClass) {
    return listOfWrapperElementsToFloatingUI[index][refClass]
      .floatinguicontainerelement;
  }


  persistPageElementReference() {
    if (typeof this.props.pageElementNode !== 'undefined') {
      pageElementReference = this.props.pageElementNode;
    }
  }
  applyFocusToPageElementReference() {
    pageElementReference.current.focus();
  }
  resetPageElementReference() {
    pageElementReference = null;
  }

  
  resetisEventListenerAddedProperty() {
    isKeyDownEventListenerConfigured = false;
  }
  unbindKeyDownEventListener() {
    document.removeEventListener('keydown', this.handleKeyPressEvent);
  }
  resetModalBoxValues() {
    this.applyFocusToPageElementReference();
    this.resetPageElementReference();
    this.resetisEventListenerAddedProperty();
    this.unbindKeyDownEventListener();
  }
  componentWillUnmount() {
    let indexOfContainerElement = this.getIndexOfContainerElement(
      this.el.className
    );
    this.removeFloatingUIContainerElement(
      indexOfContainerElement,
      this.el.className
    );
    
  }
  
  render() {
   
  let skeletonOfModal = <>
  
    {this.props.freezeLayer ? 
    this.props.freezeLayer(this.props)
    :this.props.children
  }
    </>
  return ReactDOM.createPortal(
    // Any valid React child: JSX, strings, arrays, etc.
    skeletonOfModal,
    // A DOM element
    this.el
  );
  }
}
