import { computed, defineComponent, h, ref, toRef, watchEffect } from 'vue';
import { off, on } from 'evtd';
import { useMergedState } from 'vooks';
import { depx } from 'seemly';
import { call, resolveSlot } from "../../_utils/index.mjs";
import useConfig from "../../_mixins/use-config.mjs";
import { useTheme, useThemeClass } from "../../_mixins/index.mjs";
import { splitLight } from "../styles/index.mjs";
import style from "./styles/index.cssr.mjs";
export const splitProps = Object.assign(Object.assign({}, useTheme.props), {
  direction: {
    type: String,
    default: 'horizontal'
  },
  resizeTriggerSize: {
    type: Number,
    default: 3
  },
  disabled: Boolean,
  defaultSize: {
    type: [String, Number],
    default: 0.5
  },
  'onUpdate:size': [Function, Array],
  onUpdateSize: [Function, Array],
  size: [String, Number],
  min: {
    type: [String, Number],
    default: 0
  },
  max: {
    type: [String, Number],
    default: 1
  },
  pane1Class: String,
  pane1Style: [Object, String],
  pane2Class: String,
  pane2Style: [Object, String],
  onDragStart: Function,
  onDragMove: Function,
  onDragEnd: Function,
  watchProps: Array
});
export default defineComponent({
  name: 'Split',
  props: splitProps,
  setup(props) {
    var _a;
    const {
      mergedClsPrefixRef,
      inlineThemeDisabled
    } = useConfig(props);
    const themeRef = useTheme('Split', '-split', style, splitLight, props, mergedClsPrefixRef);
    const cssVarsRef = computed(() => {
      const {
        common: {
          cubicBezierEaseInOut
        },
        self: {
          resizableTriggerColor,
          resizableTriggerColorHover
        }
      } = themeRef.value;
      return {
        '--n-bezier': cubicBezierEaseInOut,
        '--n-resize-trigger-color': resizableTriggerColor,
        '--n-resize-trigger-color-hover': resizableTriggerColorHover
      };
    });
    const resizeTriggerElRef = ref(null);
    const isDraggingRef = ref(false);
    const controlledSizeRef = toRef(props, 'size');
    const uncontrolledSizeRef = ref(props.defaultSize);
    if ((_a = props.watchProps) === null || _a === void 0 ? void 0 : _a.includes('defaultSize')) {
      watchEffect(() => uncontrolledSizeRef.value = props.defaultSize);
    }
    // use to update controlled or uncontrolled values
    const doUpdateSize = size => {
      const _onUpdateSize = props['onUpdate:size'];
      if (props.onUpdateSize) call(props.onUpdateSize, size);
      if (_onUpdateSize) call(_onUpdateSize, size);
      uncontrolledSizeRef.value = size;
    };
    const mergedSizeRef = useMergedState(controlledSizeRef, uncontrolledSizeRef);
    const firstPaneStyle = computed(() => {
      const sizeValue = mergedSizeRef.value;
      if (typeof sizeValue === 'string') {
        return {
          flex: `0 0 ${sizeValue}`
        };
      } else if (typeof sizeValue === 'number') {
        const size = sizeValue * 100;
        return {
          flex: `0 0 calc(${size}% - ${props.resizeTriggerSize * size / 100}px)`
        };
      }
    });
    const resizeTriggerStyle = computed(() => {
      return props.direction === 'horizontal' ? {
        width: `${props.resizeTriggerSize}px`,
        height: '100%'
      } : {
        width: '100%',
        height: `${props.resizeTriggerSize}px`
      };
    });
    const resizeTriggerWrapperStyle = computed(() => {
      const horizontal = props.direction === 'horizontal';
      return {
        width: horizontal ? `${props.resizeTriggerSize}px` : '',
        height: horizontal ? '' : `${props.resizeTriggerSize}px`,
        cursor: props.direction === 'horizontal' ? 'col-resize' : 'row-resize'
      };
    });
    let offset = 0;
    const handleMouseDown = e => {
      e.preventDefault();
      isDraggingRef.value = true;
      if (props.onDragStart) props.onDragStart(e);
      const mouseMoveEvent = 'mousemove';
      const mouseUpEvent = 'mouseup';
      const onMouseMove = e => {
        updateSize(e);
        if (props.onDragMove) props.onDragMove(e);
      };
      const onMouseUp = () => {
        off(mouseMoveEvent, document, onMouseMove);
        off(mouseUpEvent, document, onMouseUp);
        isDraggingRef.value = false;
        if (props.onDragEnd) props.onDragEnd(e);
        document.body.style.cursor = '';
      };
      document.body.style.cursor = resizeTriggerWrapperStyle.value.cursor;
      on(mouseMoveEvent, document, onMouseMove);
      on(mouseUpEvent, document, onMouseUp);
      const resizeTriggerEl = resizeTriggerElRef.value;
      if (resizeTriggerEl) {
        const elRect = resizeTriggerEl.getBoundingClientRect();
        if (props.direction === 'horizontal') {
          offset = e.clientX - elRect.left;
        } else {
          offset = elRect.top - e.clientY;
        }
      }
      updateSize(e);
    };
    function updateSize(event) {
      var _a, _b;
      const containerRect = (_b = (_a = resizeTriggerElRef.value) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
      if (!containerRect) return;
      const {
        direction
      } = props;
      const containerUsableWidth = containerRect.width - props.resizeTriggerSize;
      const containerUsableHeight = containerRect.height - props.resizeTriggerSize;
      const containerUsableSize = direction === 'horizontal' ? containerUsableWidth : containerUsableHeight;
      const newPxSize = direction === 'horizontal' ? event.clientX - containerRect.left - offset : event.clientY - containerRect.top + offset;
      const {
        min,
        max
      } = props;
      const pxMin = typeof min === 'string' ? depx(min) : min * containerUsableSize;
      const pxMax = typeof max === 'string' ? depx(max) : max * containerUsableSize;
      let nextPxSize = newPxSize;
      nextPxSize = Math.max(nextPxSize, pxMin);
      nextPxSize = Math.min(nextPxSize, pxMax, containerUsableSize);
      // in pixel mode
      if (typeof mergedSizeRef.value === 'string') {
        doUpdateSize(`${nextPxSize}px`);
      } else {
        // in percentage mode
        doUpdateSize(nextPxSize / containerUsableSize);
      }
    }
    const themeClassHandle = inlineThemeDisabled ? useThemeClass('split', undefined, cssVarsRef, props) : undefined;
    return {
      themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
      onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender,
      cssVars: inlineThemeDisabled ? undefined : cssVarsRef,
      resizeTriggerElRef,
      isDragging: isDraggingRef,
      mergedClsPrefix: mergedClsPrefixRef,
      resizeTriggerWrapperStyle,
      resizeTriggerStyle,
      handleMouseDown,
      firstPaneStyle
    };
  },
  render() {
    var _a, _b, _c, _d, _e;
    (_a = this.onRender) === null || _a === void 0 ? void 0 : _a.call(this);
    return h("div", {
      class: [`${this.mergedClsPrefix}-split`, `${this.mergedClsPrefix}-split--${this.direction}`, this.themeClass],
      style: this.cssVars
    }, h("div", {
      class: [`${this.mergedClsPrefix}-split-pane-1`, this.pane1Class],
      style: [this.firstPaneStyle, this.pane1Style]
    }, (_c = (_b = this.$slots)[1]) === null || _c === void 0 ? void 0 : _c.call(_b)), !this.disabled && h("div", {
      ref: "resizeTriggerElRef",
      class: `${this.mergedClsPrefix}-split__resize-trigger-wrapper`,
      style: this.resizeTriggerWrapperStyle,
      onMousedown: this.handleMouseDown
    }, resolveSlot(this.$slots['resize-trigger'], () => [h("div", {
      style: this.resizeTriggerStyle,
      class: [`${this.mergedClsPrefix}-split__resize-trigger`, this.isDragging && `${this.mergedClsPrefix}-split__resize-trigger--hover`]
    })])), h("div", {
      class: [`${this.mergedClsPrefix}-split-pane-2`, this.pane2Class],
      style: this.pane2Style
    }, (_e = (_d = this.$slots)[2]) === null || _e === void 0 ? void 0 : _e.call(_d)));
  }
});