import { useReducer, useRef, useEffect } from "react";
function $0d86e9c8f07f9a7b$export$79c0c687a5963b0a(opts, dispatch) {
  let { cursor, getKey } = opts;
  return {
    setSelectedKeys(selectedKeys) {
      dispatch((state) => ({
        ...state,
        selectedKeys
      }));
    },
    addKeysToSelection(selectedKeys) {
      dispatch((state) => {
        if (state.selectedKeys === "all") return state;
        if (selectedKeys === "all") return {
          ...state,
          selectedKeys: "all"
        };
        return {
          ...state,
          selectedKeys: /* @__PURE__ */ new Set([
            ...state.selectedKeys,
            ...selectedKeys
          ])
        };
      });
    },
    removeKeysFromSelection(selectedKeys) {
      dispatch((state) => {
        if (selectedKeys === "all") return {
          ...state,
          selectedKeys: /* @__PURE__ */ new Set()
        };
        let selection = state.selectedKeys === "all" ? new Set(state.items.map(getKey)) : new Set(state.selectedKeys);
        for (let key of selectedKeys) selection.delete(key);
        return {
          ...state,
          selectedKeys: selection
        };
      });
    },
    setFilterText(filterText) {
      dispatch((state) => ({
        ...state,
        filterText
      }));
    },
    insert(index, ...values) {
      dispatch((state) => $0d86e9c8f07f9a7b$var$insert(state, index, ...values));
    },
    insertBefore(key, ...values) {
      dispatch((state) => {
        let index = state.items.findIndex((item) => (getKey === null || getKey === void 0 ? void 0 : getKey(item)) === key);
        if (index === -1) {
          if (state.items.length === 0) index = 0;
          else return state;
        }
        return $0d86e9c8f07f9a7b$var$insert(state, index, ...values);
      });
    },
    insertAfter(key, ...values) {
      dispatch((state) => {
        let index = state.items.findIndex((item) => (getKey === null || getKey === void 0 ? void 0 : getKey(item)) === key);
        if (index === -1) {
          if (state.items.length === 0) index = 0;
          else return state;
        }
        return $0d86e9c8f07f9a7b$var$insert(state, index + 1, ...values);
      });
    },
    prepend(...values) {
      dispatch((state) => $0d86e9c8f07f9a7b$var$insert(state, 0, ...values));
    },
    append(...values) {
      dispatch((state) => $0d86e9c8f07f9a7b$var$insert(state, state.items.length, ...values));
    },
    remove(...keys) {
      dispatch((state) => {
        let keySet = new Set(keys);
        let items = state.items.filter((item) => !keySet.has(getKey(item)));
        let selection = "all";
        if (state.selectedKeys !== "all") {
          selection = new Set(state.selectedKeys);
          for (let key of keys) selection.delete(key);
        }
        if (cursor == null && items.length === 0) selection = /* @__PURE__ */ new Set();
        return {
          ...state,
          items,
          selectedKeys: selection
        };
      });
    },
    removeSelectedItems() {
      dispatch((state) => {
        if (state.selectedKeys === "all") return {
          ...state,
          items: [],
          selectedKeys: /* @__PURE__ */ new Set()
        };
        let selectedKeys = state.selectedKeys;
        let items = state.items.filter((item) => !selectedKeys.has(getKey(item)));
        return {
          ...state,
          items,
          selectedKeys: /* @__PURE__ */ new Set()
        };
      });
    },
    move(key, toIndex) {
      dispatch((state) => {
        let index = state.items.findIndex((item2) => getKey(item2) === key);
        if (index === -1) return state;
        let copy = state.items.slice();
        let [item] = copy.splice(index, 1);
        copy.splice(toIndex, 0, item);
        return {
          ...state,
          items: copy
        };
      });
    },
    moveBefore(key, keys) {
      dispatch((state) => {
        let toIndex = state.items.findIndex((item) => getKey(item) === key);
        if (toIndex === -1) return state;
        let keyArray = Array.isArray(keys) ? keys : [
          ...keys
        ];
        let indices = keyArray.map((key2) => state.items.findIndex((item) => getKey(item) === key2)).sort((a, b) => a - b);
        return $0d86e9c8f07f9a7b$var$move(state, indices, toIndex);
      });
    },
    moveAfter(key, keys) {
      dispatch((state) => {
        let toIndex = state.items.findIndex((item) => getKey(item) === key);
        if (toIndex === -1) return state;
        let keyArray = Array.isArray(keys) ? keys : [
          ...keys
        ];
        let indices = keyArray.map((key2) => state.items.findIndex((item) => getKey(item) === key2)).sort((a, b) => a - b);
        return $0d86e9c8f07f9a7b$var$move(state, indices, toIndex + 1);
      });
    },
    update(key, newValue) {
      dispatch((state) => {
        let index = state.items.findIndex((item) => getKey(item) === key);
        if (index === -1) return state;
        return {
          ...state,
          items: [
            ...state.items.slice(0, index),
            newValue,
            ...state.items.slice(index + 1)
          ]
        };
      });
    }
  };
}
function $0d86e9c8f07f9a7b$var$insert(state, index, ...values) {
  return {
    ...state,
    items: [
      ...state.items.slice(0, index),
      ...values,
      ...state.items.slice(index)
    ]
  };
}
function $0d86e9c8f07f9a7b$var$move(state, indices, toIndex) {
  toIndex -= indices.filter((index) => index < toIndex).length;
  let moves = indices.map((from) => ({
    from,
    to: toIndex++
  }));
  for (let i = 0; i < moves.length; i++) {
    let a = moves[i].from;
    for (let j = i; j < moves.length; j++) {
      let b = moves[j].from;
      if (b > a) moves[j].from--;
    }
  }
  for (let i = 0; i < moves.length; i++) {
    let a = moves[i];
    for (let j = moves.length - 1; j > i; j--) {
      let b = moves[j];
      if (b.from < a.to) a.to++;
      else b.from++;
    }
  }
  let copy = state.items.slice();
  for (let move of moves) {
    let [item] = copy.splice(move.from, 1);
    copy.splice(move.to, 0, item);
  }
  return {
    ...state,
    items: copy
  };
}
function $f86e6c1ec7da6ebb$var$reducer(data, action) {
  let selectedKeys;
  switch (data.state) {
    case "idle":
    case "error":
      switch (action.type) {
        case "loading":
        case "loadingMore":
        case "sorting":
        case "filtering":
          var _action_filterText, _action_sortDescriptor;
          return {
            ...data,
            filterText: (_action_filterText = action.filterText) !== null && _action_filterText !== void 0 ? _action_filterText : data.filterText,
            state: action.type,
            // Reset items to an empty list if loading, but not when sorting.
            items: action.type === "loading" ? [] : data.items,
            sortDescriptor: (_action_sortDescriptor = action.sortDescriptor) !== null && _action_sortDescriptor !== void 0 ? _action_sortDescriptor : data.sortDescriptor,
            abortController: action.abortController
          };
        case "update":
          var _action_updater;
          return {
            ...data,
            ...(_action_updater = action.updater) === null || _action_updater === void 0 ? void 0 : _action_updater.call(action, data)
          };
        case "success":
        case "error":
          return data;
        default:
          throw new Error(`Invalid action "${action.type}" in state "${data.state}"`);
      }
    case "loading":
    case "sorting":
    case "filtering":
      switch (action.type) {
        case "success":
          if (action.abortController !== data.abortController) return data;
          var _action_selectedKeys;
          selectedKeys = (_action_selectedKeys = action.selectedKeys) !== null && _action_selectedKeys !== void 0 ? _action_selectedKeys : data.selectedKeys;
          var _action_filterText1, _action_items, _action_sortDescriptor1;
          return {
            ...data,
            filterText: (_action_filterText1 = action.filterText) !== null && _action_filterText1 !== void 0 ? _action_filterText1 : data.filterText,
            state: "idle",
            items: [
              ...(_action_items = action.items) !== null && _action_items !== void 0 ? _action_items : []
            ],
            selectedKeys: selectedKeys === "all" ? "all" : new Set(selectedKeys),
            sortDescriptor: (_action_sortDescriptor1 = action.sortDescriptor) !== null && _action_sortDescriptor1 !== void 0 ? _action_sortDescriptor1 : data.sortDescriptor,
            abortController: void 0,
            cursor: action.cursor
          };
        case "error":
          if (action.abortController !== data.abortController) return data;
          return {
            ...data,
            state: "error",
            error: action.error,
            abortController: void 0
          };
        case "loading":
        case "loadingMore":
        case "sorting":
        case "filtering":
          var _data_abortController;
          (_data_abortController = data.abortController) === null || _data_abortController === void 0 ? void 0 : _data_abortController.abort();
          var _action_filterText2;
          return {
            ...data,
            filterText: (_action_filterText2 = action.filterText) !== null && _action_filterText2 !== void 0 ? _action_filterText2 : data.filterText,
            state: action.type,
            // Reset items to an empty list if loading, but not when sorting.
            items: action.type === "loading" ? [] : data.items,
            abortController: action.abortController
          };
        case "update":
          var _action_updater1;
          return {
            ...data,
            ...(_action_updater1 = action.updater) === null || _action_updater1 === void 0 ? void 0 : _action_updater1.call(action, data)
          };
        default:
          throw new Error(`Invalid action "${action.type}" in state "${data.state}"`);
      }
    case "loadingMore":
      switch (action.type) {
        case "success":
          var _action_selectedKeys1;
          selectedKeys = data.selectedKeys === "all" || action.selectedKeys === "all" ? "all" : /* @__PURE__ */ new Set([
            ...data.selectedKeys,
            ...(_action_selectedKeys1 = action.selectedKeys) !== null && _action_selectedKeys1 !== void 0 ? _action_selectedKeys1 : []
          ]);
          var _action_items1, _action_sortDescriptor2;
          return {
            ...data,
            state: "idle",
            items: [
              ...data.items,
              ...(_action_items1 = action.items) !== null && _action_items1 !== void 0 ? _action_items1 : []
            ],
            selectedKeys,
            sortDescriptor: (_action_sortDescriptor2 = action.sortDescriptor) !== null && _action_sortDescriptor2 !== void 0 ? _action_sortDescriptor2 : data.sortDescriptor,
            abortController: void 0,
            cursor: action.cursor
          };
        case "error":
          if (action.abortController !== data.abortController) return data;
          return {
            ...data,
            state: "error",
            error: action.error
          };
        case "loading":
        case "sorting":
        case "filtering":
          var _data_abortController1;
          (_data_abortController1 = data.abortController) === null || _data_abortController1 === void 0 ? void 0 : _data_abortController1.abort();
          var _action_filterText3;
          return {
            ...data,
            filterText: (_action_filterText3 = action.filterText) !== null && _action_filterText3 !== void 0 ? _action_filterText3 : data.filterText,
            state: action.type,
            // Reset items to an empty list if loading, but not when sorting.
            items: action.type === "loading" ? [] : data.items,
            abortController: action.abortController
          };
        case "loadingMore":
          var _action_abortController;
          (_action_abortController = action.abortController) === null || _action_abortController === void 0 ? void 0 : _action_abortController.abort();
          return data;
        case "update":
          var _action_updater2;
          return {
            ...data,
            ...(_action_updater2 = action.updater) === null || _action_updater2 === void 0 ? void 0 : _action_updater2.call(action, data)
          };
        default:
          throw new Error(`Invalid action "${action.type}" in state "${data.state}"`);
      }
    default:
      throw new Error(`Invalid state "${data.state}"`);
  }
}
function $f86e6c1ec7da6ebb$export$bc3384a35de93d66(options) {
  const { load, sort, initialSelectedKeys, initialSortDescriptor, getKey = (item) => item.id || item.key, initialFilterText = "" } = options;
  let [data, dispatch] = useReducer($f86e6c1ec7da6ebb$var$reducer, {
    state: "idle",
    error: void 0,
    items: [],
    selectedKeys: initialSelectedKeys === "all" ? "all" : new Set(initialSelectedKeys),
    sortDescriptor: initialSortDescriptor,
    filterText: initialFilterText
  });
  const dispatchFetch = async (action, fn) => {
    let abortController = new AbortController();
    try {
      dispatch({
        ...action,
        abortController
      });
      var _action_filterText;
      let previousFilterText = (_action_filterText = action.filterText) !== null && _action_filterText !== void 0 ? _action_filterText : data.filterText;
      var _action_sortDescriptor;
      let response = await fn({
        items: data.items.slice(),
        selectedKeys: data.selectedKeys,
        sortDescriptor: (_action_sortDescriptor = action.sortDescriptor) !== null && _action_sortDescriptor !== void 0 ? _action_sortDescriptor : data.sortDescriptor,
        signal: abortController.signal,
        cursor: action.type === "loadingMore" ? data.cursor : void 0,
        filterText: previousFilterText,
        loadingState: data.state
      });
      var _response_filterText;
      let filterText = (_response_filterText = response.filterText) !== null && _response_filterText !== void 0 ? _response_filterText : previousFilterText;
      dispatch({
        type: "success",
        ...response,
        abortController
      });
      if (filterText && filterText !== previousFilterText && !abortController.signal.aborted) dispatchFetch({
        type: "filtering",
        filterText
      }, load);
    } catch (e) {
      dispatch({
        type: "error",
        error: e,
        abortController
      });
    }
  };
  let didDispatchInitialFetch = useRef(false);
  useEffect(() => {
    if (!didDispatchInitialFetch.current) {
      dispatchFetch({
        type: "loading"
      }, load);
      didDispatchInitialFetch.current = true;
    }
  }, []);
  return {
    items: data.items,
    selectedKeys: data.selectedKeys,
    sortDescriptor: data.sortDescriptor,
    isLoading: data.state === "loading" || data.state === "loadingMore" || data.state === "sorting" || data.state === "filtering",
    loadingState: data.state,
    error: data.error,
    filterText: data.filterText,
    getItem(key) {
      return data.items.find((item) => getKey(item) === key);
    },
    reload() {
      dispatchFetch({
        type: "loading"
      }, load);
    },
    loadMore() {
      if (data.state === "loading" || data.state === "loadingMore" || data.state === "filtering" || data.cursor == null) return;
      dispatchFetch({
        type: "loadingMore"
      }, load);
    },
    sort(sortDescriptor) {
      dispatchFetch({
        type: "sorting",
        sortDescriptor
      }, sort || load);
    },
    ...$0d86e9c8f07f9a7b$export$79c0c687a5963b0a({
      ...options,
      getKey,
      cursor: data.cursor
    }, (fn) => {
      dispatch({
        type: "update",
        updater: fn
      });
    }),
    setFilterText(filterText) {
      dispatchFetch({
        type: "filtering",
        filterText
      }, load);
    }
  };
}
export {
  $f86e6c1ec7da6ebb$export$bc3384a35de93d66 as $
};
