// @ts-nocheck
import { cloneVNode } from 'vue';
import { defineComponent, ref, onMounted, onUpdated, onUnmounted } from 'vue';
import { alignElement, alignPoint } from 'dom-align';
import { findDOMNode } from '../_util/props-util';
import { isSamePoint, monitorResize } from './util';
const alignProps = {
  align: Object,
  target: [Object, Function],
  onAlign: Function,
  monitorBufferTime: Number,
  monitorWindowResize: Boolean,
  disabled: Boolean
};

function getElement(func) {
  if (typeof func !== 'function') return null;
  return func();
}

function getPoint(point) {
  if (typeof point !== 'object') {
    if (!point) return null;

    if (getElement(point)) {
      const {
        offsetLeft: pageX,
        offsetTop: pageY
      } = getElement(point);
      return {
        pageX,
        pageY
      };
    }
  }

  ;
  return point;
}

export default defineComponent({
  name: 'Align',
  props: alignProps,

  setup(props, {
    slots,
    expose
  }) {
    const cacheRef = ref({});
    const nodeRef = ref();

    function forceAlign() {
      const {
        disabled,
        target,
        onAlign,
        align
      } = props;
      const source = findDOMNode(nodeRef.value);

      if (!disabled && target && source) {
        let result;
        const element = getElement(target),
              point = getPoint(target);
        cacheRef.value.element = element;
        cacheRef.value.point = point;

        if (element) {
          result = alignElement(source, element, align);
        } else if (point) {
          result = alignPoint(source, point, align);
        }

        if (onAlign && result) {
          onAlign(source, result);
        }
      }
    }

    const resizeMonitor = ref({
      cancel: () => {}
    });
    const sourceResizeMonitor = ref({
      cancel: () => {}
    });

    function goAlign() {
      const {
        target
      } = props,
            element = getElement(target),
            point = getPoint(target); // popupSize or popupDom change

      const dom = findDOMNode(nodeRef.value);

      if (dom !== sourceResizeMonitor.value.element) {
        sourceResizeMonitor.value.cancel();
        sourceResizeMonitor.value.element = dom;
        sourceResizeMonitor.value.cancel = monitorResize(dom, forceAlign);
      } // (target || point) change


      if (cacheRef.value.element != element || !isSamePoint(cacheRef.value.point, point)) {
        forceAlign();

        if (resizeMonitor.value.element != element) {
          resizeMonitor.value.cancel();
          resizeMonitor.value.element = element;
          resizeMonitor.value.cancel = monitorResize(element, forceAlign);
        }
      }
    }

    onMounted(() => {
      goAlign();
    });
    onUpdated(() => {
      goAlign();
    });
    onUnmounted(() => {
      resizeMonitor.value.cancel();
      sourceResizeMonitor.value.cancel();
    });
    expose({
      forceAlign
    });
    return () => {
      var _slots$default;

      const child = (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots);

      if (child) {
        return cloneVNode(child[0], {
          ref: nodeRef
        }, true);
      }
    };
  }

});