import React,{ useState,useEffect } from 'react';
import { keyNames,keyCodes } from '../../accessibility-utils/keyCodes';
import uniqueNumber from '../../utils/uniqueId';
import componentCategories from '../../docs-utils/componentCategories';
import componentGroups from '../../docs-utils/componentGroups';

const useAccessNavigationManager = (props,configuration={})=>{ 
    let { activecss,wrap,focus,keyName={},grid,onKeyDown } = configuration;
    
    //let [ activeDescendantValue,setActiveDescendantValue ] = useState();
    // class AccessNavigationManager extends React.Component{
    //     constructor(props){
            //super(props)
            //this.state = { activedescendantId : undefined }
            // this.rootEle = null;
            // this.uitype = null;
            // this.onKeyDownCallBack = null;
            // this.rootEleId = uniqueNumber();
            // this.getRootRef = this.getRootRef.bind(this);
            // this.currentNodeEle = null;
            // this.currentNodeIndex = 0;
            let rootEle = null;
            //const uitype = null;
            //const onKeyDownCallBack = null;
            let rootEleId = uniqueNumber();
            let currentNodeEle = null;
            let currentNodeIndex = 0;
            let isFocused;
            // this.focusGridView = this.focusGridView.bind(this);
            // this.focusFirst = this.focusFirst.bind(this);
            // this.getFocusableTree = this.getFocusableTree.bind(this);
            // this.defaultKeyPress = this.defaultKeyPress.bind(this);
            // this.getNextRowCurrentIndexEle = this.getNextRowCurrentIndexEle.bind(this);
            // this.getNextRowEle = this.getNextRowEle.bind(this);
            // this.focusManager = this.focusManager.bind(this);
            // this.wrapNextRowChangeIndex = this.wrapNextRowChangeIndex.bind(this);
            // this.setCurrentNodeIndex = this.setCurrentNodeIndex.bind(this);
            // this.getItemProps = this.getItemProps.bind(this);
            // this.keyMoving = this.keyMoving.bind(this);
            // this.navigationProps = this.navigationProps.bind(this);
        //}

        const getRootRef = ()=>{
          if(rootEle === null){
            rootEle = document.querySelector(`[data-aria-rootid="${rootEleId}"]`)
          }
          return rootEle;
        }

        // useEffect(()=>{
        //     return ()=>{ rootEle = null }
        // },[])
        
        // componentWillUnmount(){
        //   rootEle = null;
        // }

        const wrapNextRowChangeIndex = (mode,node)=>{
          if(mode === 'next'){
            currentNodeIndex = 0;
          }else{
            /** not get parent children in Selection element */
            if(node.getAttribute("data-aria-row") === 'true' && !node.contains(currentNodeEle)){
              currentNodeIndex = (node && node.querySelectorAll('[data-aria-col="true"]').length) + 1;
            }
          }
        }

        const getFocusableTree =(root,mode)=>{
            let walker = document.createTreeWalker(
              root,
              NodeFilter.SHOW_ELEMENT,
              (
                (mode === 'next' || mode === 'previous') ?
                { 
                  acceptNode: (node)=>{ 
                    if(node.getAttribute('data-aria-col') === 'true' || node.getAttribute('data-aria-item') === 'true'){
                      return NodeFilter.FILTER_ACCEPT; 
                    }
                    else{
                      wrapNextRowChangeIndex(mode,node);
                      return NodeFilter.FILTER_SKIP; 
                    }
                  } 
                } 
                :
                (mode === 'nextRow') ?
                { 
                  acceptNode: function(node) { 
                    if(node.getAttribute('data-aria-row') === 'true'){
                      return NodeFilter.FILTER_ACCEPT; 
                    }
                    else{
                      return NodeFilter.FILTER_SKIP; 
                    }
                  } 
                }
                :
                {
                  acceptNode: (node)=>{ 
                    if(node.getAttribute('data-aria-row') === 'true' && (currentNodeIndex <= (node && node.querySelectorAll('[data-aria-col="true"]').length))){
                      return NodeFilter.FILTER_ACCEPT; 
                    }
                    else{
                      return NodeFilter.FILTER_SKIP; 
                    }
                  }
                }
              )
            )
            return walker;
        }

        const focusManager = (mode)=>{
            let nextNode;
            let rootEle = getRootRef();
            let walker = getFocusableTree(rootEle,mode);
            //slet { focusVisible,focusProps } = useFocusVisible({});
            let node = (currentNodeEle ? currentNodeEle : walker.currentNode);
            if (rootEle.contains(node)) {
              walker.currentNode = node;
              nextNode = mode === 'next' ? walker.nextNode() : walker.previousNode();
              if(nextNode !== null) { 
                currentNodeEle = nextNode;
                if(mode === 'next'){
                  currentNodeIndex++
                }
                else{
                  currentNodeIndex--
                }
              }
              else{
                if(wrap){
                  walker.currentNode = rootEle;  
                  nextNode = mode === 'next' ? walker.nextNode() :walker.lastChild();
                  if(mode === 'next'){
                    currentNodeIndex++
                  }
                  else{
                    currentNodeIndex--
                  }
                }
                else{
                  return
                }
              }
              walker.currentNode = node;
              if(walker.currentNode && currentNodeEle){
                activecss && walker.currentNode.classList.remove(activecss);
                
                //walker.currentNode.setAttribute('aria-selected','false')
                //this.setState({ariaSelected:undefined})
              }
            }
            if(wrap){
              currentNodeEle = nextNode;
            }
            if(currentNodeEle) {
              activecss && currentNodeEle.classList.add(activecss);
              //currentNodeEle.setAttribute('aria-selected','true')
              //this.setState({activedescendantId:this.currentNodeEle.id})
              //setActiveDescendantValue( ()=>{ return currentNodeEle.id } )
              !focus && currentNodeEle.scrollIntoView({ block: 'nearest' })
              focus && currentNodeEle.focus();
            }
            return currentNodeEle;
        }

        const getNextRowCurrentIndexEle = (nextSibling)=>{
          let walker = getFocusableTree(nextSibling,'next')
          for(let i=0; i < currentNodeIndex; i++){
            currentNodeEle = walker.nextNode();
          }
        }

        const getNextRowEle = (mode,currentRoot,nextChildRow)=>{
          let rootEle = getRootRef();
          let gridWalker = getFocusableTree(rootEle,(nextChildRow || 'nextRow'));
          let node = (currentNodeEle ? currentNodeEle : gridWalker.currentNode);
          let previousNode;
          if(rootEle.contains(node)){
            gridWalker.currentNode = currentRoot || node;
            previousNode = gridWalker.currentNode;
          }
          gridWalker.parentNode();
          let nextSibling = mode === 'last'? gridWalker.lastChild() : mode === 'next' ? gridWalker.nextNode() : gridWalker.previousNode();
          let nextSiblingChildLength = nextSibling && nextSibling.querySelectorAll('[data-aria-col="true"]').length || 0;
          return { nextSibling,previousNode,nextSiblingChildLength };
        }

        const focusGridView = (mode)=>{
          let rootEle = getRootRef();
          let {nextSibling,previousNode,nextSiblingChildLength} = getNextRowEle(mode)
          if(nextSibling !==null){
            if(currentNodeIndex <= nextSiblingChildLength){
              getNextRowCurrentIndexEle(nextSibling)
            }
            else{
              let {nextSibling} = getNextRowEle(mode,'','nextChildRow')
              nextSibling && getNextRowCurrentIndexEle(nextSibling)
            }
          }
          else{
            if(wrap){
              let {nextSibling,nextSiblingChildLength} = getNextRowEle(mode === 'next' ? 'next' : 'last',rootEle)
              if(currentNodeIndex <= nextSiblingChildLength){
                getNextRowCurrentIndexEle(nextSibling)
              }
            }
            else{
              return
            }
          }
          if(previousNode && currentNodeEle && activecssf){
            previousNode.classList.remove(activecss);
          }
          if(currentNodeEle && activecss){
            currentNodeEle.classList.add(activecss);
            focus && currentNodeEle.focus();
          }
        }

        const setCurrentNodeIndex = ()=>{
          let rootEle = getRootRef();
          let walkerRow = getFocusableTree(rootEle,'nextRow'); 
          walkerRow.currentNode = currentNodeEle;
          let getChildNodes = walkerRow.parentNode();
          if(getChildNodes && getChildNodes.children){
            Object.keys(getChildNodes.children).forEach((element,index)=>{
              if(getChildNodes.children[element] === currentNodeEle){
                currentNodeIndex = index+1;
              }
            })
          }
          else{
            return
          }
        }

        const focusFirst = (itemId)=>{
            let rootEle = getRootRef();
            let from = rootEle.querySelector(`[data-aria-itemid="${itemId}"]`);
            let walker = getFocusableTree(rootEle,'next');
            let node = (currentNodeEle ? currentNodeEle : walker.currentNode);
            if(rootEle.contains(node) && activecss){
              node && node.classList.remove(activecss);
            }
            if(!from){ 
              currentNodeEle = walker.nextNode() 
            }
            else{
              currentNodeEle = from;
              setCurrentNodeIndex()
            }
            if(currentNodeEle && activecss){
              currentNodeEle.classList.add(activecss);
              focus && currentNodeEle.focus();
            }
            return currentNodeEle;
        }

        const keyMoving = (e,keys)=>{
          if((keys.toLowerCase()) === 'left' || (keys.toLowerCase()) === 'up'){
            if((keys.toLowerCase()) === 'up'){ 
              grid ? focusGridView('previous') : focusManager('previous');
              e && e.preventDefault(); 
            }
            else{
              focusManager('previous');
            }
          }else if((keys.toLowerCase()) === 'right' || (keys.toLowerCase()) === 'down'){
            if((keys.toLowerCase()) === 'down'){ 
              grid ? focusGridView('next') : focusManager('next');
              e && e.preventDefault();
            }
            else{
              focusManager('next');
            }
          }
          
          else if((keys.toLowerCase()) === 'tabforward' || (keys.toLowerCase()) === 'tabbackward' ){
            if((keys.toLowerCase()) === 'tabforward'){
              e && e.preventDefault();
              focusManager('next');
            }
            else{
              focusManager('previous');
            }
            
          }
        }

        const defaultKeyPress = (e)=>{
            onKeyDown && onKeyDown(e);
            let { keyCode } = e;
            let { arrowleft,arrowright,arrowtop,arrowbottom } = keyNames;
            let { leftArrow,rightArrow,topArrow,bottomArrow } = keyCodes;
            if(Object.keys(keyName).length){
              Object.keys(keyName).forEach((keys)=>{
                keyName[keys].forEach((value)=>{
                  if(value.indexOf('shift') !== -1 && event.shiftKey){
                    let splitedKey = value.split('+')[1];
                    if((splitedKey.toLowerCase()) === (e.key.toLowerCase())){
                      keyMoving(e,keys)
                    }
                  }
                  else{
                    if((value.toLowerCase()) === (e.key.toLowerCase())){
                      keyMoving(e,keys)
                    }
                  }
                })
              })
            }
            else{
                if(keyCode === 37){
                  grid && focusManager('previous');
                }
                if( keyCode === 39){
                  grid && focusManager('next');
                } 
                if(keyCode === 40){
                  e && e.preventDefault();
                  grid && focusGridView('next');
                  !grid && focusManager('next');
                }
                if(keyCode === 38){
                  e && e.preventDefault();
                  grid && focusGridView('previous')
                  !grid && focusManager('previous');
                }
            }
            if(keyCode === 13){
                currentNodeEle && currentNodeEle.click();
            }   
        }

        const getItemProps = (id)=>{
          //let { role,id,dataAriaItem={} } = props;
          let genratedRandomId = id || uniqueNumber();
          let dataAriaItems = { 
            'data-aria-item' : 'true',
            'data-aria-itemid' : genratedRandomId,
            'onKeyDown' : (e)=>{ defaultKeyPress(e) }
            //id : genratedRadomId, 
            //role,
            //'aria-selected' : this.state.ariaSelected,
            //...dataAriaItem
            
          }
          let dataAriaCol = { 
            'data-aria-col' : 'true', 
            'data-aria-itemid' : genratedRandomId,
            'onKeyDown' : defaultKeyPress
          }
        //   if(uitype === 'listbox' || uitype === 'grid'){
        //     dataAriaItems['onKeyDown'] = defaultKeyPress.bind(this,this.onKeyDownCallBack);
        //     dataAriaCol['onKeyDown'] = defaultKeyPress.bind(this,onKeyDownCallBack)
        //   }
        
          return {
            dataAriaCol,
            dataAriaColDisabled : { 'data-aria-col' : 'false','aria-disabled' : 'true' },
            dataAriaRow : { 'data-aria-row' : 'true' },
            dataAriaItem:dataAriaItems,
            dataAriaItemDisabled : { 'data-aria-item' : 'false','aria-disabled' : 'true' },
            itemId : genratedRandomId 
          }
        }

        const navigationProps = ()=>{
          //let { onKeyDown,type,popupOpen,listElementProps={},targetElementProps={},inputProps={} } = props || {};
          //uitype = type;
          //onKeyDownCallBack = onKeyDown;
          //let rootElementProps = {};
        //   let listElementProp = {
        //     role: 'listbox', 
        //     id: rootEleId,
        //     ...listElementProps
        //   }
        //  rootElementProps
        //   if(type === 'combobox'){
        //     //rootElementProps['role'] = "combobox"; 
        //     //rootElementProps['aria-owns'] = this.rootEleId;
        //     rootElementProps['data-aria-rootid'] = rootEleId
        //   }
        //   else if(type === 'grid'){
        //     rootElementProps['role'] = "grid"; 
        //     rootElementProps['data-aria-rootid'] = rootEleId
        //   }
        //   else{
        //     listElementProp['aria-activedescendant'] = activeDescendantValue
        //     rootElementProps['data-aria-rootid'] = rootEleId
        //   }
          return{
            rootElementProps : {
                'data-aria-rootid' : rootEleId
            },
            focusFirst : focusFirst,
            //focusManager : focusManager,
            inputProps : { 
              onKeyDown : defaultKeyPress,
            //   'aria-activedescendant' : activeDescendantValue,
            //   'aria-owns' : rootEleId,
            //   'role':'combobox', 
            //   ...inputProps
            },
            getItemProps : getItemProps,
            isFocused : isFocused
            //listElementProps : listElementProp,
            // targetElementProps:{
            //   'aria-controls' : rootEleId,
            //   'aria-haspopup': listElementProps.role ||'listbox',
            //   'aria-expanded': popupOpen ? 'true' : 'false',
            //   ...targetElementProps
            // }  
          }             
        }

        return navigationProps();

        // render(){
        //     return <WrappedComponent navigationProps={this.navigationProps}/>
        // }
    //}
    // return hoistStatics(AccessNavigationManager,WrappedComponent);
}

export default useAccessNavigationManager;

// if (__DOCS__) {
//   AccessNavigationManager.docs = {
//     componentGroup: componentGroups.Components,
//     folderName : componentCategories.Accessibility
//   };
// }