import React, { Component, useRef, useEffect, useState, useCallback } from 'react';
import componentCategories from '../../docs-utils/componentCategories';
import componentGroups from '../../docs-utils/componentGroups'; //import { uniqueNumber } from "@zohodesk/utils/src/index";

import constants from './Popper.constants.json'; // utills

import debounce from './utills/debounce';
import removeClose from './utills/removeClose';
import handleOpenPopupPositionChange from './utills/handleOpenPopupPositionChange';
import getNeedArrow from './utills/getNeedArrow';
import lastOpenedGroupFunc from './utills/getLastOpenedGroup';
import getScrollDebounceTime from './utills/getScrollDebounceTime';
import getCloseOnScrollPopup from './utills/getCloseOnScrollPopup';
import getIsAbsolutePopup from './utills/getIsAbsolutePopup';
import getCustomPositionOrder from './utills/getCustomPositionOrder';
import handleCloseLastOpenedGroup from './utills/handleCloseLastOpenedGroup';
import handleGetNeedPrevent from './utills/handleGetNeedPrevent';
import handleDocumentMouseDown from './utills/handleDocumentMouseDown';
import handleResize from './utills/handleResize';
import handleDocumentFocus from './utills/handleDocumentFocus';
import documentClickHandler1 from './utills/documentClickHandler1';
import openPopupOnly from './utills/openPopupOnly';
import closePopupOnly from './utills/closePopupOnly';
import handlePopupResize from './utills/handlePopupResize';
import documentClickHandler from './utills/documentClickHandler';
import documentKeyupHandler from './utills/documentKeyupHandler'; //

import useConstructor from '../../custom-hooks/statehooks';
import useId from '../../custom-hooks/useId';
import { add, groupBasedFilter, popOut, getData, cancelOthers } from './Popper.manage';
import { absolutePositionMapping, rtlAbsolutePositionMapping, rtlFixedPositionMapping } from './Popper.constants.json';

function usePopper(props) {
  let dropElement = useRef(null);
  let size = useRef(null);
  let placeHolderElement = useRef(null);
  let isAbsolutePopup = useRef(props.isAbsolutePopup);
  let needPopupArrow = useRef(props.needPopupArrow);
  let customPositionOrder = useRef(props.customPositionOrder);
  let scrollDebounceTime = useRef(props.popupScrollDebounceTime);
  let lastOpenedGroup = useRef(lastOpenedGroupFunc() || []); // let closeOnScroll = closeOnScrollPopup;

  let handleScrollFunc = debounce(handleScroll, scrollDebounceTime);
  let id = useId(props.id);
  let groupName = props.groupName ? props.groupName : 'global';
  let [isPopupOpen, onIsPopupOpen] = useState(props.isPopupOpen);
  let [position, onPosition] = useState(constants.absolutePositionMapping.bottomCenter);
  let [height, onHeight] = useState('0px');
  let [isPopupReady, onIsPopupReady] = useState(props.isPopupOpen || false);
  let [positions, onPositions] = useState({});
  let [positionsOffset, onPositionsOffset] = useState({});
  let [targetOffset, onTargetOffset] = useState({});
  let [popupOffset, onPopupOffset] = useState({});
  let [isAbsolutePositioningNeeded, onIsAbsolutePositioningNeeded] = useState(true); //

  let popupObserver = new ResizeObserver(handlePopupResize.bind(onSetSizeRef, size)); // life cycles

  let onSetSizeRef = value => {
    size = value;
  };

  let cancelGloabl = useCallback(() => {
    onIsPopupOpen(false);
    onIsPopupReady(false);
  }, [isPopupOpen, isPopupReady]);
  let popupStatus = useCallback(() => {
    return isPopupOpen;
  }, [isPopupOpen]); // constructor

  useConstructor(() => {
    let methods = {
      onHeight,
      popupStatus,
      onIsPopupReady,
      onPositions,
      onPositionsOffset,
      onTargetOffset,
      onPopupOffset,
      onIsAbsolutePositioningNeeded
    };
    let data = {
      props,
      methods,
      isPopupOpen //remove from here

    };
    add(id, {
      cancel: cancelGloabl
    }, groupName, data);
  }); // not done

  function togglePopup(e, defaultPosition) {
    //useCallBack
    removeClose(e);
    cancelOthers(id, groupName);

    if (isPopupOpen) {
      cancelGloabl();
      return false;
    } else {
      handlePopupPosition(defaultPosition);
      return true;
    }
  }

  function handlePopupPosition() {
    let defaultPosition = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : constants.absolutePositionMapping.bottomCenter;
    let isResizeHandling = arguments.length > 1 ? arguments[1] : undefined;
    // isResizeHandling --->>> Window resize and dropBox resize
    // const { direction } = this.context;
    let direction = 'rtl';
    const needArrow = getNeedArrow(props.isArrow, props.needPopupArrow);
    const isAbsolute = getIsAbsolutePopup(isAbsolutePositioningNeeded, isAbsolutePopup);
    const customOrder = getCustomPositionOrder(props.customOrder, props.customPositionOrder);

    if (direction === 'rtl') {
      defaultPosition = isAbsolute ? rtlAbsolutePositionMapping[defaultPosition] : rtlFixedPositionMapping[defaultPosition];
    } else {
      defaultPosition = isAbsolute ? absolutePositionMapping[defaultPosition] : defaultPosition;
    }

    if (!placeHolderElement.current && !dropElement.current) {
      onIsPopupOpen(true);
      onIsPopupReady(true);
      return;
    }

    const setPosition = () => {
      requestAnimationFrame(() => {
        const scrollContainer = placeHolderElement.current.closest('[data-scroll=true]') || document.body;
        const betterPosition = viewPort.betterView(dropElement.current, placeHolderElement.current, defaultPosition, scrollContainer, {
          needArrow,
          isAbsolute,
          customOrder
        });
        const {
          view,
          views,
          viewsOffset,
          targetOffset,
          popupOffset
        } = betterPosition || {};

        if (position !== view || !isPopupReady) {
          onIsPopupReady(true);
          onPosition(view);
          onPositions(views);
          onPositionsOffset(viewsOffset);
          onTargetOffset(targetOffset);
          onPopupOffset(popupOffset);
          onIsAbsolutePositioningNeeded(isAbsolute);
        }
      });
    };

    if (isResizeHandling) {
      setPosition();
    } else {
      this.defaultPosition = defaultPosition;
      this.setState({
        isPopupOpen: true,
        isPopupReady: false
      }, setPosition);
    }
  }

  function handleScroll(e) {
    handleOpenPopupPositionChange();
    const {
      closeOnScroll
    } = getCloseOnScrollPopup(props);

    if (isPopupReady) {
      console.log('onscrollPopupREady');
    }

    if (isPopupReady && closeOnScroll) {
      console.log(this, 'handle Scroll');
      togglePopup(e);
    }
  }

  function getTargetRef(el) {
    placeHolderElement = el;
  }

  function getContainerRef(el) {
    dropElement = el;
  } // life cycles


  useEffect(() => {
    const {
      needResizeHandling: propResizeHandling
    } = props;

    if (isPopupReady && dropElement.current && (propResizeHandling !== undefined ? propResizeHandling : needResizeHandling)) {
      popupObserver.replaceObservationElement(dropElement.current);
    } else if (!isPopupReady) {
      size = null;
      popupObserver.disconnect();
    }
  }, [isPopupReady]); // receioprops

  useEffect(() => {
    if (typeof props.isPopupOpen !== 'undefined' && props.isPopupOpen !== isPopupOpen) {
      onIsPopupOpen(props.isPopupOpen);
      onIsPopupReady(props.isPopupOpen);
    }
  }, [props.isPopupOpen]);
  useEffect(() => {
    const groupPopups = getData() || [];

    if (groupPopups.length === 1) {
      document.addEventListener('click', documentClickHandler, false);
      document.addEventListener('keyup', documentKeyupHandler, false);
      props.isParentBasedAutoPlacement && document.addEventListener('scroll', handleScroll, true);
      window.addEventListener('resize', handleResize);
      document.addEventListener('click', documentClickHandler1, true);
      document.addEventListener('mousedown', handleDocumentMouseDown, true);
      document.addEventListener('focus', handleDocumentFocus, true);
    }
  }, []);
  let stateDetails = {
    isPopupOpen,
    position,
    height,
    isPopupReady,
    positions,
    positionsOffset,
    targetOffset,
    popupOffset,
    isAbsolutePositioningNeeded
  };
  let dataToOut = { ...props,
    ...stateDetails,
    openPopupOnly: openPopupOnly.bind(groupName),
    closePopupOnly: closePopupOnly.bind(isPopupOpen, cancelGloabl),
    togglePopup: togglePopup,
    removeClose: removeClose,
    getTargetRef: getTargetRef,
    getContainerRef: getContainerRef
  };
  return dataToOut;
}

if (false) {
  usePopper.docs = {
    componentGroup: componentGroups.Components,
    folderName: componentCategories.UCL
  };
}

export default usePopper;