import { Fragment as _Fragment, createVNode as _createVNode, mergeProps as _mergeProps, createElementVNode as _createElementVNode } from "vue";
// Components
import { VBtn } from "../VBtn/index.js";
import { VDefaultsProvider } from "../VDefaultsProvider/index.js";
import { makeVSnackbarProps, VSnackbar } from "../VSnackbar/VSnackbar.js"; // Composables
import { useSnackbarQueue } from "./queue.js";
import { useDelay } from "../../composables/delay.js";
import { useDocumentVisibility } from "../../composables/documentVisibility.js";
import { useLocale } from "../../composables/locale.js"; // Utilities
import { computed, mergeProps, ref, shallowRef, toRef, triggerRef, watch } from 'vue';
import { genericComponent, omit, propsFactory, useRender } from "../../util/index.js"; // Types
export const makeVSnackbarQueueProps = propsFactory({
  // TODO: Port this to Snackbar on dev
  closable: [Boolean, String],
  closeText: {
    type: String,
    default: '$vuetify.dismiss'
  },
  collapsed: Boolean,
  displayStrategy: {
    type: String,
    default: 'hold'
  },
  modelValue: {
    type: Array,
    default: () => []
  },
  totalVisible: {
    type: [Number, String],
    default: 1
  },
  gap: {
    type: [Number, String],
    default: 8
  },
  ...omit(makeVSnackbarProps(), ['modelValue', 'collapsed', 'queueIndex', 'queueGap'])
}, 'VSnackbarQueue');
export const VSnackbarQueue = genericComponent()({
  name: 'VSnackbarQueue',
  inheritAttrs: false,
  props: makeVSnackbarQueueProps(),
  emits: {
    'update:modelValue': val => true
  },
  setup(props, {
    attrs,
    emit,
    slots
  }) {
    const {
      t
    } = useLocale();
    const documentVisibility = useDocumentVisibility();
    const queue = useSnackbarQueue(props);
    const isHovered = shallowRef(false);
    const {
      runOpenDelay,
      runCloseDelay
    } = useDelay({
      openDelay: 0,
      closeDelay: 500
    }, val => {
      isHovered.value = val;
      updateDynamicProps();
    });
    let _lastId = 0;
    const visibleItems = ref([]);
    const limit = toRef(() => Number(props.totalVisible));
    watch(() => props.modelValue.length, showNext);
    function removeItem(id) {
      visibleItems.value = visibleItems.value.filter(x => x.id !== id);
      if (visibleItems.value.length === 0) {
        isHovered.value = false;
      }
      showNext();
    }
    function showNext() {
      if (!props.modelValue.length) return;
      const activeCount = visibleItems.value.filter(x => x.active).length;
      if (activeCount >= limit.value) {
        if (props.displayStrategy !== 'overflow') return;

        // Dismiss oldest active items to make room
        visibleItems.value.filter(x => x.active).slice(limit.value - 1).forEach(item => {
          item.active = false;
          item.onDismiss?.('overflow');
        });
      }
      const [next, ...rest] = props.modelValue;
      emit('update:modelValue', rest);
      const item = typeof next === 'string' ? {
        text: next
      } : next;
      const {
        promise,
        success,
        error,
        onDismiss,
        ...itemProps
      } = item;
      const newItem = {
        id: _lastId++,
        item: {
          ...(promise ? {
            timeout: -1,
            loading: true
          } : {}),
          ...itemProps
        },
        active: true,
        onDismiss
      };
      visibleItems.value.unshift(newItem);
      updateDynamicProps();
      promise?.then(data => {
        if (!newItem.active) return;
        newItem.item = success?.(data) ?? {
          ...newItem.item,
          timeout: 1
        };
        updateDynamicProps();
        triggerRef(visibleItems);
      }, data => {
        if (!newItem.active) return;
        newItem.item = error?.(data) ?? {
          ...newItem.item,
          timeout: 1
        };
        updateDynamicProps();
        triggerRef(visibleItems);
      });
    }
    function dismiss(id, reason) {
      const item = visibleItems.value.find(x => x.id === id);
      if (!item) return;
      item.active = false;
      item.onDismiss?.(reason);
      updateDynamicProps();
    }
    function clear() {
      emit('update:modelValue', []);
      visibleItems.value.toReversed().forEach((item, i) => setTimeout(() => {
        item.active = false;
        item.onDismiss?.('cleared');
      }, 100 * i));
    }
    const btnProps = computed(() => ({
      color: typeof props.closable === 'string' ? props.closable : undefined,
      text: t(props.closeText)
    }));
    function updateDynamicProps() {
      let activeIndex = 0;
      visibleItems.value.forEach(({
        item,
        active
      }) => {
        item.queueIndex = activeIndex;
        if (active) activeIndex++;
      });
      if (!props.collapsed || isHovered.value) {
        visibleItems.value.forEach(({
          item
        }) => item.collapsed = undefined);
        return;
      }
      for (const {
        item
      } of visibleItems.value) {
        item.collapsed = item.queueIndex > 0 ? {
          width: queue.lastItemSize.value.width,
          height: queue.lastItemSize.value.height
        } : undefined;
      }
    }
    watch(queue.lastItemSize, updateDynamicProps);
    watch(() => props.collapsed, updateDynamicProps);
    useRender(() => {
      const hasActions = !!(props.closable || slots.actions);
      const snackbarProps = omit(VSnackbar.filterProps(props), ['modelValue', 'collapsed']);
      const pauseAll = documentVisibility.value === 'hidden' || props.collapsed && isHovered.value;
      return _createElementVNode(_Fragment, null, [visibleItems.value.map(({
        id,
        item,
        active
      }) => slots.item ? _createVNode(VDefaultsProvider, {
        "defaults": {
          VSnackbar: item
        }
      }, {
        default: () => [slots.item({
          item
        })]
      }) : _createVNode(VSnackbar, _mergeProps({
        "key": id
      }, attrs, snackbarProps, item, pauseAll ? {
        timeout: -1
      } : {}, {
        "queueGap": Number(props.gap),
        "contentProps": mergeProps(snackbarProps.contentProps, {
          onMouseenter: runOpenDelay,
          onMouseleave: () => runCloseDelay()
        }),
        "modelValue": active,
        "onUpdate:modelValue": () => dismiss(id, 'auto'),
        "onAfterLeave": () => removeItem(id)
      }), {
        header: slots.header ? () => slots.header?.({
          item
        }) : undefined,
        text: slots.text ? () => slots.text?.({
          item
        }) : undefined,
        actions: hasActions ? () => _createElementVNode(_Fragment, null, [!slots.actions ? _createVNode(VBtn, _mergeProps(btnProps.value, {
          "onClick": () => dismiss(id, 'dismissed')
        }), null) : _createVNode(VDefaultsProvider, {
          "defaults": {
            VBtn: btnProps.value
          }
        }, {
          default: () => [slots.actions({
            item,
            props: {
              onClick: () => dismiss(id, 'dismissed')
            }
          })]
        })]) : undefined
      }))]);
    });
    return {
      clear
    };
  }
});
//# sourceMappingURL=VSnackbarQueue.js.map