import { InjectionKey } from 'vue';

type PopoverProvideType = {
  getSourceEl: (el: HTMLElement) => void;
  getTargetEl: (el: HTMLElement) => void;
};

export const POPOVERPROVIDEKEY: InjectionKey<PopoverProvideType> = Symbol(
  'popover-provide-key'
);

export const placements = [
  'top',
  'top-start',
  'top-end',
  'bottom',
  'bottom-start',
  'bottom-end',
  'left',
  'left-start',
  'left-end',
  'right',
  'right-start',
  'right-end',
] as const;
export type PlacementType = typeof placements[number];
export const triggers = ['click', 'hover', 'focus', 'contextmenu'] as const;
export type TriggerType = typeof triggers[number];

const throllte = (fn: any, times: number = 20) => {
  let startTime = 0;
  return (context: any = window) => {
    let endTime = Date.now();
    if (endTime - startTime > times) {
      startTime = endTime;
      fn.call(context);
    }
  };
};

export const getLastNotTextChild = (
  childs: any //Array<{ el: HTMLElement; [key: string]: any }>
) => {
  let last = null;
  let i = childs.length;
  if (!i) return last;
  while (i--) {
    const item = childs[i];
    if (item.nodeType === 1) {
      return item;
    }
  }
  return null;
};

const getScrollContainers = (el: HTMLElement) => {
  let parent = el.parentNode;
  let scrollContainers = [];
  while (parent) {
    if (['BODY', 'HTML', '#document'].includes(parent.nodeName)) {
      scrollContainers.push(parent);
    } else if (/scroll|auto/.test(getComputedStyle(parent as any).overflow)) {
      scrollContainers.push(parent);
    }
    parent = parent.parentNode;
  }
  return scrollContainers;
};

const onWatchScroll = (containers: ParentNode[], fn: () => void) => {
  containers.forEach((dom) => {
    (dom as Element).addEventListener('scroll', fn);
  });
};
const offWatchScroll = (containers: ParentNode[], fn: () => void) => {
  containers.forEach((dom) => {
    (dom as Element).removeEventListener('scroll', fn);
  });
};
