import { cloneDeep as H } from "es-toolkit";
import { merge as w } from "es-toolkit/compat";
import { resolveComponent as V, openBlock as u, createElementBlock as _, Fragment as P, renderList as G, normalizeClass as S, createBlock as f, mergeProps as b, resolveDynamicComponent as k, createSlots as W, withCtx as y, createElementVNode as v, createCommentVNode as L, createVNode as O, createTextVNode as U, toDisplayString as D, nextTick as z, toRefs as Y, ref as R } from "vue";
import q from "./useValidation.js";
import { LLLV_CHANGE_TRIGGERS as A } from "./constants.js";
import { t as M } from "./locale.js";
import { persistentStorage as N } from "./storage.js";
import J from "./Button.js";
import K from "./Checkbox.js";
import Q from "./DatePicker.js";
import X from "./Input.js";
import Z from "./InputOptions.js";
import I from "./Radio.js";
import $ from "./Select.js";
import { _ as ee } from "./_plugin-vue_export-helper-CHgC5LLL.js";
const te = {
  "filter-button-group": "_filter-button-group_jowFx"
}, le = {
  name: "ll-filters",
  components: {
    "ll-button": J,
    "ll-checkbox": K,
    "ll-input": X,
    "ll-input-options": Z,
    "ll-radio": I,
    "ll-select": $,
    DatePicker: Q
  },
  props: {
    /**
     * Whether to disable the Apply button
     */
    disableApply: Boolean,
    /**
     * Whether to disable the Clear button
     */
    disableClear: Boolean,
    /**
     * Whether to disable the sticky filters
     * If disabled, a default pre-selected value(s) can be added to
     * the filter component's attributes
     */
    disablePersistency: Boolean,
    /**
     * Filters schema
     */
    schema: {
      type: Array,
      default: () => []
    },
    /**
     * Validation schema function that returns an object
     */
    validationSchema: {
      type: Function,
      default: () => () => {
      }
    }
  },
  emits: ["change", "submit", "reset"],
  setup(l) {
    const { validationSchema: r } = Y(l), i = r.value(), s = R({}), t = R();
    function o() {
      if ((i == null ? void 0 : i.toString()) !== "[object Object]")
        return;
      s.value = Object.keys(i).reduce((d, h) => (d[h] = void 0, d), {});
      const p = Object.entries(i).reduce((d, [h, m]) => (d[h] = m.map((c) => c(s)), d), {});
      t.value = q({ rules: p, values: s }), t.value.validate();
    }
    return {
      validation: t,
      validationValues: s,
      initValidation: o
    };
  },
  data() {
    return {
      applyText: M("ll.apply"),
      clearText: M("ll.clear"),
      filters: {},
      filterValues: {},
      forceRenderCount: 0
    };
  },
  watch: {
    filterValues: {
      /**
       * Maps filters to a partcular object structure:
       * @param {IFilterSchemaItem} newFilterValues all selected filters
       * @returns {IFilter}
       */
      handler: function(l) {
        const r = Object.keys(l).reduce((i, s) => {
          const t = this.schema[s];
          if (!t || !t.fieldToFilter)
            return i;
          const o = l[s];
          if (o === "" || o == null)
            return i;
          const p = t.attributes.trackBy || "id", d = typeof o == "object", h = typeof t.type == "object", m = h && t.attributes.multiple || !h && t.type.includes("ll-select") && (t.attributes.multiple || !t.attributes.single), c = m ? (
            // local storage might have item stored as an object from the old Select
            (Array.isArray(o) ? o : [o]).map((a) => a[p])
          ) : d ? [o[p]] : [o], e = t.groupedWith;
          return e && (c[0] = {
            index: e,
            value: l[e]
          }, c.push({
            index: Number(s),
            value: l[s]
          })), c.length && (i[t.fieldToFilter] = {
            // don't add to `filters` if no filterBy
            filterBy: c,
            filterType: t.type,
            // Informs the applied filter count
            isMultiple: m,
            ..."fn" in t && { customFilter: t.fn }
          }), i;
        }, {});
        this.filters = r, this.$emit("change", r);
      },
      deep: !0,
      immediate: !0
    },
    filters() {
      this.validation && this.updateValidationValues();
    }
  },
  async created() {
    this.initFilterValues(), await z(), this.initValidation(), this.applyFilters({ trigger: A.LOAD });
  },
  methods: {
    initFilterValues() {
      if (this.disablePersistency) {
        this.filterValues = this.getDefaultFilterValues();
        return;
      }
      this.filterValues = this.getPersistentFilterValues() || this.getDefaultFilterValues();
    },
    /**
     * Apply the selected filters and save them to localStorage.
     * ListView calls this method using a ref to Filters.
     * The trigger option is used in ListView.
     * @param {object} [options] - optional parameters
     * @param {string} [options.trigger] - the action that triggered this function call
     */
    async applyFilters({ trigger: l = A.APPLY } = {}) {
      this.validation && (await this.validation.validate(), this.validation.hasErrors) || (this.disablePersistency || this.persistFilterValues(this.filterValues), this.$emit("submit", { trigger: l }));
    },
    resetFilters() {
      this.filterValues = this.getDefaultFilterValues(), this.forceRenderCount++, this.disablePersistency || this.persistFilterValues(this.filterValues), this.$nextTick(() => {
        this.$emit("reset");
      });
    },
    /**
     * Returns pre-defined filter values to become the default values
     */
    getDefaultFilterValues() {
      return this.schema.reduce((l, r, i) => (r.type === "ll-checkbox" ? l[i] = r.attributes.checked || !1 : Object.prototype.hasOwnProperty.call(r.attributes, "modelValue") && (l[i] = r.attributes.modelValue), l), {});
    },
    /**
     * Intended for external use, when filter values need to be set for the user
     */
    setFilterValues(l) {
      this.filterValues = w({}, this.filterValues, l), this.forceRenderCount++;
    },
    updateValidationValues() {
      const l = Object.keys(this.validationSchema());
      this.schema.forEach((r, i) => {
        const s = r.fieldToFilter;
        if (l.includes(s)) {
          const o = this.filters[s], p = o ? o.isMultiple ? o.filterBy : o.filterBy[0] : this.filterValues[i];
          this.validationValues[s] = p;
        }
      });
    },
    /**
     * Change handler for filter fields
     */
    onChange(l, r, i) {
      var s;
      (s = l.on) != null && s.change && l.on.change(r, i);
    },
    /**
     * Select input event handler for filter fields
     */
    onSelectInput(l, r, i) {
      l === void 0 ? delete this.filterValues[i] : this.filterValues[i] = l, this.onChange(r, this.filterValues, i);
    },
    /**
     * Get filter values from local storage.
     * @returns {any}
     */
    getPersistentFilterValues() {
      return N.get("filter-values");
    },
    /**
     * Clone new filterValues to remove reactivity, and save them to localStorage.
     * @param {object} newValues - the filterValues to be persisted in localStorage
     */
    persistFilterValues(l) {
      N.set("filter-values", H(l));
    }
  }
}, se = { class: "ll-grid grid-cols-4 md:grid-cols-12" }, ie = ["data-test"], oe = ["innerHTML"], re = ["innerHTML"];
function ae(l, r, i, s, t, o) {
  var c;
  const p = V("ll-select"), d = V("ll-checkbox"), h = V("ll-radio"), m = V("ll-button");
  return u(), _("div", se, [
    (u(!0), _(P, null, G(i.schema, (e, a) => {
      var g, F, T, C, x, j, B, E;
      return u(), _(P, null, [
        e.hidden ? L("", !0) : (u(), _("div", {
          key: `${a} ${t.forceRenderCount}`,
          class: S(["field-wrapper col-span-4 md:col-span-3", { "max-md:hidden": !e.type, "flex items-end": e.type === "ll-checkbox" }]),
          "data-test": `filter|${e.fieldToFilter}`
        }, [
          e.type === "ll-select" ? (u(), f(p, b({
            key: 0,
            ref_for: !0
          }, e.attributes, {
            error: ((g = s.validation) == null ? void 0 : g.fields[e.fieldToFilter]) && ((F = s.validation) == null ? void 0 : F.getError(e.fieldToFilter)),
            label: e.label,
            "model-value": t.filterValues[a],
            "onUpdate:modelValue": (n) => o.onSelectInput(n, e, a)
          }), null, 16, ["error", "label", "model-value", "onUpdate:modelValue"])) : e.type === "ll-checkbox" ? (u(), f(d, b({
            key: 1,
            checked: t.filterValues[a],
            "onUpdate:checked": (n) => t.filterValues[a] = n
          }, { ref_for: !0 }, e.attributes, {
            "error-text": ((T = s.validation) == null ? void 0 : T.fields[e.fieldToFilter]) && ((C = s.validation) == null ? void 0 : C.getError(e.fieldToFilter)),
            label: e.label,
            "onUpdate:checked": (n) => o.onChange(e, t.filterValues, a)
          }), null, 16, ["checked", "onUpdate:checked", "error-text", "label"])) : e.type === "ll-radio" ? (u(), f(h, b({
            key: 2,
            checked: t.filterValues[a],
            "onUpdate:checked": (n) => t.filterValues[a] = n
          }, { ref_for: !0 }, e.attributes, {
            "error-text": ((x = s.validation) == null ? void 0 : x.fields[e.fieldToFilter]) && ((j = s.validation) == null ? void 0 : j.getError(e.fieldToFilter)),
            label: e.label,
            "onUpdate:checked": (n) => o.onChange(e, t.filterValues, a)
          }), null, 16, ["checked", "onUpdate:checked", "error-text", "label"])) : e.type ? (u(), f(k(e.type), b({
            key: 3,
            ref_for: !0
          }, e.attributes, {
            modelValue: t.filterValues[a],
            "onUpdate:modelValue": [(n) => t.filterValues[a] = n, (n) => o.onChange(e, t.filterValues, a)],
            "error-text": ((B = s.validation) == null ? void 0 : B.fields[e.fieldToFilter]) && ((E = s.validation) == null ? void 0 : E.getError(e.fieldToFilter)),
            label: e.label
          }), W({ _: 2 }, [
            e.slots && e.slots.selected ? {
              name: "selected",
              fn: y(({ option: n }) => [
                (u(), f(k(e.slots.selected), b({ ref_for: !0 }, n.props), null, 16))
              ]),
              key: "0"
            } : void 0,
            e.slots && e.slots.option ? {
              name: "option",
              fn: y(({ option: n }) => [
                (u(), f(k(e.slots.option), b({ ref_for: !0 }, n.props), null, 16))
              ]),
              key: "1"
            } : void 0,
            e.slots && e.slots.prepend ? {
              name: "prepend",
              fn: y(() => [
                v("span", {
                  innerHTML: e.slots.prepend
                }, null, 8, oe)
              ]),
              key: "2"
            } : void 0,
            e.slots && e.slots.append ? {
              name: "append",
              fn: y(() => [
                v("span", {
                  innerHTML: e.slots.append
                }, null, 8, re)
              ]),
              key: "3"
            } : void 0
          ]), 1040, ["modelValue", "onUpdate:modelValue", "error-text", "label"])) : L("", !0)
        ], 10, ie))
      ], 64);
    }), 256)),
    v("div", {
      class: S(["button-grid col-span-4 flex items-end justify-end md:col-span-12", l.$style["filter-button-group"]])
    }, [
      O(m, {
        secondary: "",
        "data-test": "button|reset-filters",
        disabled: i.disableClear,
        onClick: o.resetFilters
      }, {
        default: y(() => [
          U(D(t.clearText), 1)
        ]),
        _: 1
      }, 8, ["disabled", "onClick"]),
      O(m, {
        primary: "",
        "data-test": "button|apply-filters",
        disabled: i.disableApply || ((c = s.validation) == null ? void 0 : c.hasErrors),
        onClick: o.applyFilters
      }, {
        default: y(() => [
          U(D(t.applyText), 1)
        ]),
        _: 1
      }, 8, ["disabled", "onClick"])
    ], 2)
  ]);
}
const ne = {
  $style: te
}, Te = /* @__PURE__ */ ee(le, [["render", ae], ["__cssModules", ne]]);
export {
  Te as default
};
//# sourceMappingURL=Filters.js.map
