import { ref, watch, nextTick, onBeforeUnmount } from 'vue';
import { state } from "./stateMgr.js";

function getNumberFromKeyEvent(event) {
    if (event.keyCode >= 96 && event.keyCode <= 105) {
        return event.keyCode - 96;
    } else if (event.keyCode >= 48 && event.keyCode <= 57) {
        return event.keyCode - 48;
    }
    return null;
}
export const ArrowHorizontalKeyHandler = (event) => {
  if (event.key == "ArrowRight") {
    const idx = state.sortedElements.indexOf(String(state.activeIndex));
    state.activeIndex = state.sortedElements[(idx+1)%state.sortedElements.length];
  } else if (event.key == "ArrowLeft") {
    const idx = state.sortedElements.indexOf(String(state.activeIndex))
    state.activeIndex = state.sortedElements[(idx+state.sortedElements.length-1)%state.sortedElements.length];
  }
}
export const ArrowVerticalKeyHandler = (event) => {
  if (event.key == "ArrowDown") {
    const idx = state.sortedElements.indexOf(String(state.activeIndex))
    state.activeIndex = state.sortedElements[(idx+1)%state.sortedElements.length];
    event.preventDefault();
  } else if (event.key == "ArrowUp") {
    const idx = state.sortedElements.indexOf(String(state.activeIndex))
    state.activeIndex = state.sortedElements[(idx+state.sortedElements.length-1)%state.sortedElements.length];
    event.preventDefault();
  }
}
export const NumberKeyHandler = (event) => {
  let i;
  if ((i = getNumberFromKeyEvent(event)) != null) {
    if (state.elements[i] != undefined) {
      event.stopPropagation();
      event.preventDefault();
      state.activeIndex = i;
      state.elements[i].focus();
      state.elements[i].click();
    }
  }
}


export const EnterHandler = (event) => {
  if (event.key == "Enter"){
    if (state.hasOwnProperty("activeElement") && state.activeElement) {
      event.stopPropagation();
      if (state.activeElement.tagName != "BUTTON"){
        event.preventDefault();
      }
      state.activeElement.click();
    }
  }
}


export const handleActive = (props, keydownHandlers) => {
  const ownCopy = keydownHandlers.map((f) => (e) => f(e));
  const currActive = ref(1);
  state.activeIndex = 1;
  const handle = () => {
    if (props.active){
      state.activeIndex = currActive.value;
      for (var i = 0; i < keydownHandlers.length; i++) {
        document.addEventListener("keydown", ownCopy[i]);
      }
    } else {
      currActive.value = state.activeIndex;
      for (var i = 0; i < ownCopy.length; i++) {
        document.removeEventListener("keydown", ownCopy[i]);
      }
    }
  }
  onBeforeUnmount(() => {
    // Cleanup
    for (var i = 0; i < ownCopy.length; i++) {
      document.removeEventListener("keydown", ownCopy[i]);
    }
  });
  watch(() => props.active, handle);
  handle();
}

export const vAutofocus = {
  mounted(el, binding, vnode, prevVnode) {
    if (binding.value == undefined || binding.value) {
      state.activeIndex = getId(el);
    }
  }
}

export function getId(el) {
  for (var key in state.elements) {
    if (state.elements[key] == el){
      return key;
    }
  }
}



const add = (el) => {
  const focus = () => {
    if (state.activeElement !== el) {
      state.activeIndex = val;
      state.activeElement = el;
    }
  }

  const blur = (e) => {
    if (e.relatedTarget === null) {
      state.activeElement = undefined;
      state.activeIndex = undefined;
    }
  }
  let val;
  if (el.dataset["tabindex"]) {
    val = el.dataset["tabindex"];
  } else {
    val = Object.keys(state.elements).length+1;
  }
  el.tabIndex = val;
  state.elements[val] = el;
  el.addEventListener("focus", focus);
  el.addEventListener("blur", blur);
  el.blurcb = blur;
  el.focuscb = focus;
};

const remove = (el) => {
  delete el.removeAttribute("tabindex");
  delete state.elements[getId(el)]
  // el.removeEventListener("blur", el.blurfn);
  // el.removeEventListener("focus", el.focusfn);
}

export const vIndex = {
  updated(el, binding, vnode, prevVnode) {
    if (binding.oldValue != binding.value){
      if (binding.oldValue) {
        remove(el);
      } else {
        add(el);
      }
    }
  },
  mounted(el, binding, vnode, prevVnode) {
    add(el);
  },
  beforeUnmount(el, binding, vnode, prevVnode) {
    remove(el);
  }
}
