'use strict';

var index = require('./index-C_OnxXhP.js');
var index_esm = require('./index.esm-C1i_NocP.js');
var limetype = require('./limetype-BlG0Apxb.js');
var nonNull = require('./non-null-BMnREsqJ.js');
var _baseIsEqual = require('./_baseIsEqual-Ba8g_ag_.js');
var _MapCache = require('./_MapCache-DHOVMBKi.js');
require('./_Uint8Array-CXHKqIsu.js');

/** `Object#toString` result references. */
var stringTag = '[object String]';

/**
 * Checks if `value` is classified as a `String` primitive or object.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is a string, else `false`.
 * @example
 *
 * _.isString('abc');
 * // => true
 *
 * _.isString(1);
 * // => false
 */
function isString(value) {
  return typeof value == 'string' ||
    (!_MapCache.isArray(value) && _MapCache.isObjectLike(value) && _MapCache.baseGetTag(value) == stringTag);
}

/**
 * Performs a deep comparison between two values to determine if they are
 * equivalent.
 *
 * **Note:** This method supports comparing arrays, array buffers, booleans,
 * date objects, error objects, maps, numbers, `Object` objects, regexes,
 * sets, strings, symbols, and typed arrays. `Object` objects are compared
 * by their own, not inherited, enumerable properties. Functions and DOM
 * nodes are compared by strict equality, i.e. `===`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Lang
 * @param {*} value The value to compare.
 * @param {*} other The other value to compare.
 * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 * @example
 *
 * var object = { 'a': 1 };
 * var other = { 'a': 1 };
 *
 * _.isEqual(object, other);
 * // => true
 *
 * object === other;
 * // => false
 */
function isEqual(value, other) {
  return _baseIsEqual.baseIsEqual(value, other);
}

const limeQueryFilterBuilderCss = () => `.expression-with-promotion{display:flex;flex-direction:column;gap:1rem}limel-button{width:100%}.query-options-section{margin-top:1rem}`;

const LimeQueryFilterBuilderComponent = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.expressionChange = index.createEvent(this, "expressionChange");
        this.handleAddFirstCondition = () => {
            const newExpression = {
                key: '',
                op: index_esm.nt.EQUALS,
                exp: '',
            };
            this.expressionChange.emit(newExpression);
        };
        this.handlePromoteAndAdd = () => {
            if (!this.expression) {
                return;
            }
            // Wrap current expression in AND and add a new comparison
            const newExpression = {
                op: index_esm.nt.AND,
                exp: [
                    this.expression,
                    {
                        key: '',
                        op: index_esm.nt.EQUALS,
                        exp: '',
                    },
                ],
            };
            this.expressionChange.emit(newExpression);
        };
        this.handleExpressionChange = (event) => {
            var _a;
            event.stopPropagation();
            this.expressionChange.emit((_a = event.detail) !== null && _a !== void 0 ? _a : undefined);
        };
    }
    render() {
        if (!this.expression) {
            return this.renderEmptyState();
        }
        // Check if we need to show promotion UI (comparison or NOT)
        if (this.needsPromotion()) {
            return this.renderWithPromotionButton();
        }
        // AND/OR groups handle their own Add buttons
        return (index.h("limebb-lime-query-filter-expression", { platform: this.platform, context: this.context, limetype: this.limetype, activeLimetype: this.activeLimetype, expression: this.expression, onExpressionChange: this.handleExpressionChange }));
    }
    needsPromotion() {
        if (!this.expression) {
            return false;
        }
        // Basic comparison needs promotion
        if ('key' in this.expression) {
            return true;
        }
        // NOT needs promotion
        return this.expression.op === index_esm.nt.NOT;
    }
    renderEmptyState() {
        return (index.h("limel-button", { label: "Condition", icon: {
                name: 'plus_math',
                title: 'Add',
            }, onClick: this.handleAddFirstCondition }));
    }
    renderWithPromotionButton() {
        return (index.h("div", { class: "expression-with-promotion" }, index.h("limebb-lime-query-filter-expression", { platform: this.platform, context: this.context, limetype: this.limetype, activeLimetype: this.activeLimetype, expression: this.expression, onExpressionChange: this.handleExpressionChange }), index.h("limel-button", { label: "Add another condition", icon: "plus_math", onClick: this.handlePromoteAndAdd })));
    }
};
LimeQueryFilterBuilderComponent.style = limeQueryFilterBuilderCss();

const orderByEditorCss = () => `:host(limebb-lime-query-order-by-editor){display:flex;flex-direction:column;gap:1rem;padding:1rem 0}.header{display:flex;justify-content:space-between;align-items:center;gap:1rem}.header h4{margin:0;font-size:1rem;font-weight:600;color:rgb(var(--contrast-1000))}.order-by-list{display:flex;flex-direction:column;gap:1rem;border:1px solid rgb(var(--contrast-300));border-radius:0.25rem;background-color:rgb(var(--contrast-50));min-height:4rem}.order-by-item{padding:0.5rem;border-radius:0.25rem;transition:background-color 0.2s}.order-by-item:hover{background-color:rgb(var(--contrast-100))}.actions{display:flex;width:100%}.summary{display:flex;justify-content:space-between;align-items:center;padding-top:0.5rem;border-top:1px solid rgb(var(--contrast-300))}.summary .count{font-size:0.875rem;font-weight:500;color:rgb(var(--contrast-900))}limel-header.is-narrow{--header-top-right-left-border-radius:0;width:calc(100% + var(--limebb-lime-query-builder-visual-mode-padding) * 2);margin-left:calc(var(--limebb-lime-query-builder-visual-mode-padding) * -1)}.empty-state{padding:0 2rem;text-align:center;color:rgb(var(--contrast-700))}`;

const OrderByEditor = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.change = index.createEvent(this, "change");
        /**
         * Optional label
         */
        this.label = 'Sort Order';
        this.items = [];
        this.handleItemChange = (index) => (event) => {
            event.stopPropagation();
            const newItems = [...this.items];
            if (event.detail === null) {
                // Remove item
                newItems.splice(index, 1);
            }
            else {
                // Update item
                newItems[index] = event.detail;
            }
            this.items = newItems;
            this.emitChange();
        };
        this.handleAddSortField = () => {
            // Add new item with empty path and ASC direction
            this.items = [...this.items, { '': 'ASC' }];
            this.emitChange();
        };
    }
    componentWillLoad() {
        if (this.value && this.value.length > 0) {
            this.items = [...this.value];
        }
    }
    handleValueChange(newValue) {
        if (!newValue) {
            return;
        }
        // Check if items have changed
        const itemsChanged = newValue.length !== this.items.length ||
            !newValue.every((item, index) => {
                const currentItem = this.items[index];
                if (!currentItem)
                    return false;
                const itemKey = Object.keys(item)[0];
                const currentKey = Object.keys(currentItem)[0];
                return (itemKey === currentKey &&
                    item[itemKey] === currentItem[currentKey]);
            });
        if (itemsChanged) {
            this.items = newValue.length > 0 ? [...newValue] : [];
        }
    }
    render() {
        return (index.h(index.Host, { key: '6ef5ee3cf7b67cc0f821272f9d552eab48b60065' }, this.renderEmptyState(), this.renderOrderByEditor()));
    }
    renderEmptyState() {
        if (this.limetype) {
            return null;
        }
        return (index.h("div", { class: "empty-state" }, index.h("p", null, "Select a limetype to configure sorting")));
    }
    renderOrderByEditor() {
        if (!this.limetype) {
            return null;
        }
        return [
            this.renderHeader(),
            this.renderOrderByList(),
            this.renderActions(),
        ];
    }
    renderHeader() {
        return (index.h("limel-header", { class: "is-narrow", heading: this.label, icon: "sorting_arrows" }));
    }
    renderOrderByList() {
        if (this.items.length === 0) {
            return null;
        }
        return (index.h("div", { class: "order-by-list" }, this.items.map((item, index) => this.renderItem(item, index))));
    }
    renderActions() {
        return (index.h("limel-button", { label: "Add Sort Field", icon: "plus_math", onClick: this.handleAddSortField }));
    }
    renderItem(item, index$1) {
        const propertyPath = Object.keys(item)[0] || '';
        return (index.h("limebb-lime-query-order-by-item", { key: `${propertyPath}-${index$1}`, class: "order-by-item", platform: this.platform, context: this.context, limetype: this.limetype, item: item, onItemChange: this.handleItemChange(index$1) }));
    }
    emitChange() {
        this.change.emit(this.items);
    }
    static get watchers() { return {
        "value": [{
                "handleValueChange": 0
            }]
    }; }
};
OrderByEditor.style = orderByEditorCss();

const RELATION_PROPERTY_TYPES = [
    'belongsto',
    'hasone',
    'hasmany',
    'hasandbelongstomany',
];
const DEFAULT_ALLOWED_PROPERTY_TYPES = [
    'string',
    'text',
    'phone',
    'integer',
    'decimal',
    'percent',
    'time',
    'date',
    'year',
    'quarter',
    'month',
    'yesno',
    'link',
    'user',
    'xml',
    'option',
    'set',
    'file',
    'system',
];

const allNonSystemPropertyTypes = DEFAULT_ALLOWED_PROPERTY_TYPES.filter((propertyType) => propertyType !== 'system');
allNonSystemPropertyTypes.push(...RELATION_PROPERTY_TYPES);
const LimetypeField = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.change = index.createEvent(this, "change");
        /**
         * A list of property fields that should be updated when the selected limetype changes.
         */
        this.propertyFields = [];
        /**
         * The name of this field. May be used as reference when a property mapping
         * depends on the selected limetype.
         */
        this.fieldName = 'limetype';
        this.handleChange = (event) => {
            event.stopPropagation();
            let selectedLimetype = '';
            if (event.detail && 'value' in event.detail) {
                selectedLimetype = event.detail.value;
            }
            this.change.emit(selectedLimetype || undefined);
        };
    }
    componentWillLoad() {
        const language = this.platform
            .get(index_esm.n.Application)
            .getLanguage();
        this.collator = new Intl.Collator(language, {
            numeric: true,
            sensitivity: 'base',
        });
    }
    componentShouldUpdate(newValue, oldValue, property) {
        var _a, _b;
        return (property !== 'formInfo' ||
            !isEqual((_a = newValue === null || newValue === void 0 ? void 0 : newValue.schema) === null || _a === void 0 ? void 0 : _a.oneOf, (_b = oldValue === null || oldValue === void 0 ? void 0 : oldValue.schema) === null || _b === void 0 ? void 0 : _b.oneOf));
    }
    render() {
        var _a;
        const options = this.getLimeTypes().map(limeTypeToOption);
        options.sort((a, b) => this.collator.compare(a.text, b.text));
        let selectedOption = options.find((option) => option.value === this.value);
        let invalid = this.invalid;
        if (this.value && !selectedOption) {
            invalid = true;
            options.unshift({
                text: ((_a = this.limeTypeRepository.getLimeType(this.value)) === null || _a === void 0 ? void 0 : _a.localname.singular) || this.value,
                value: this.value,
            });
            selectedOption = options[0];
        }
        const emptyOption = {
            text: '',
            value: '',
        };
        options.unshift(emptyOption);
        return (index.h("limel-select", { key: '20a7d5eb86c746d11ad805083be5ef9f5fd2397d', label: this.label, options: options, value: selectedOption, required: this.required, helperText: this.helperText, invalid: invalid, disabled: this.disabled || this.readonly, onChange: this.handleChange }));
    }
    componentWillRender() {
        this.updatePropertyFields(this.value || '');
    }
    getLimeTypes() {
        var _a, _b;
        let limetypes = this.limetypes;
        if ((_b = (_a = this.formInfo) === null || _a === void 0 ? void 0 : _a.schema) === null || _b === void 0 ? void 0 : _b.oneOf) {
            limetypes = this.formInfo.schema.oneOf
                .map((choice) => choice.const)
                .filter(isString);
        }
        if (!limetypes) {
            return this.limeTypeRepository.getLimeTypes();
        }
        return limetypes
            .map((limetype) => this.limeTypeRepository.getLimeType(limetype))
            .filter(nonNull.isNonNull);
    }
    updatePropertyFields(selectedLimetype) {
        for (const field of this.propertyFields) {
            field.limetype = selectedLimetype;
            if (field.allowedPropertyTypes === DEFAULT_ALLOWED_PROPERTY_TYPES) {
                field.allowedPropertyTypes = allNonSystemPropertyTypes;
            }
        }
    }
    get limeTypeRepository() {
        return this.platform.get(index_esm.n.LimeTypeRepository);
    }
};
const limeTypeToOption = (limetype$1) => ({
    text: limetype$1.localname.singular,
    value: limetype$1.name,
    icon: limetype.getIcon(limetype$1),
});

exports.limebb_lime_query_filter_builder = LimeQueryFilterBuilderComponent;
exports.limebb_lime_query_order_by_editor = OrderByEditor;
exports.limebb_limetype_field = LimetypeField;
