import { NumberValue, RecordValue, Schema, StringValue } from "@coveo/bueno";
import { buildFacetConditionsManager, buildNumericFacet, buildNumericRange, buildSearchStatus, buildTabManager } from "@coveo/headless";
import { LitElement, html, nothing } from "lit";
import { customElement, property, state as decorators_js_state } from "lit/decorators.js";
import { when } from "lit/directives/when.js";
import atomic_rating_tw_css from "../../common/atomic-rating/atomic-rating.tw.css.js";
import { renderRating } from "../../common/atomic-rating/rating.js";
import { parseDependsOn } from "../../common/facets/depends-on.js";
import facet_common_tw_css from "../../common/facets/facet-common.tw.css.js";
import { renderFacetContainer } from "../../common/facets/facet-container/facet-container.js";
import { renderFacetHeader } from "../../common/facets/facet-header/facet-header.js";
import { renderFacetPlaceholder } from "../../common/facets/facet-placeholder/facet-placeholder.js";
import facet_value_checkbox_tw_css from "../../common/facets/facet-value-checkbox/facet-value-checkbox.tw.css.js";
import { renderFacetValueLink } from "../../common/facets/facet-value-link/facet-value-link.js";
import { renderFacetValuesGroup } from "../../common/facets/facet-values-group/facet-values-group.js";
import { initializePopover } from "../../common/facets/popover/popover-type.js";
import { ValidatePropsController } from "../../common/validate-props-controller/validate-props-controller.js";
import { arrayConverter } from "../../../converters/array-converter.js";
import { booleanConverter } from "../../../converters/boolean-converter.js";
import { bindStateToController } from "../../../decorators/bind-state.js";
import { bindingGuard } from "../../../decorators/binding-guard.js";
import { bindings } from "../../../decorators/bindings.js";
import { errorGuard } from "../../../decorators/error-guard.js";
import { withTailwindStyles } from "../../../decorators/with-tailwind-styles.js";
import { FocusTargetController } from "../../../utils/accessibility-utils.js";
import { mapProperty } from "../../../utils/props-utils.js";
import star from "../../../images/star.js";
function _ts_decorate(decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : null === desc ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if ("object" == typeof Reflect && "function" == typeof Reflect.decorate) r = Reflect.decorate(decorators, target, key, desc);
    else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function _ts_metadata(k, v) {
    if ("object" == typeof Reflect && "function" == typeof Reflect.metadata) return Reflect.metadata(k, v);
}
class AtomicRatingRangeFacet extends LitElement {
    connectedCallback() {
        super.connectedCallback();
        if (void 0 === this.maxValueInIndex) this.maxValueInIndex = this.numberOfIntervals;
    }
    get _filterFacetCount() {
        return this.filterFacetCount ?? true;
    }
    initialize() {
        if (this.tabsIncluded.length > 0 && this.tabsExcluded.length > 0) console.warn('Values for both "tabs-included" and "tabs-excluded" have been provided. This could lead to unexpected behaviors.');
        this.searchStatus = buildSearchStatus(this.bindings.engine);
        this.tabManager = buildTabManager(this.bindings.engine);
        this.initializeFacet();
        this.initializeDependenciesManager();
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        if (!this.isConnected) this.dependenciesManager?.stopWatching();
    }
    get focusTarget() {
        if (!this.headerFocus) this.headerFocus = new FocusTargetController(this, this.bindings);
        return this.headerFocus;
    }
    get isHidden() {
        return !this.valuesToRender.length || this.searchStatusState.hasError || !this.facet.state.enabled;
    }
    initializeFacet() {
        const options = {
            facetId: this.facetId,
            field: this.field,
            numberOfValues: this.numberOfIntervals,
            currentValues: this.generateCurrentValues(),
            sortCriteria: 'descending',
            generateAutomaticRanges: false,
            filterFacetCount: this._filterFacetCount,
            injectionDepth: this.injectionDepth,
            tabs: {
                included: [
                    ...this.tabsIncluded
                ],
                excluded: [
                    ...this.tabsExcluded
                ]
            }
        };
        this.facet = buildNumericFacet(this.bindings.engine, {
            options
        });
        this.facetId = this.facet.state.facetId;
        const facetInfo = {
            label: ()=>this.bindings.i18n.t(this.label),
            facetId: this.facetId,
            element: this,
            isHidden: ()=>this.isHidden
        };
        this.bindings.store.registerFacet('numericFacets', {
            ...facetInfo,
            format: (value)=>this.formatFacetValue(value),
            content: (value)=>this.ratingContent(value)
        });
        initializePopover(this, {
            ...facetInfo,
            hasValues: ()=>!!this.valuesToRender.length,
            numberOfActiveValues: ()=>this.numberOfSelectedValues
        });
    }
    get scaleFactor() {
        return (this.maxValueInIndex ?? this.numberOfIntervals) / this.numberOfIntervals;
    }
    get numberOfSelectedValues() {
        return this.facetState.values.filter(({ state })=>'selected' === state).length;
    }
    initializeDependenciesManager() {
        this.dependenciesManager = buildFacetConditionsManager(this.bindings.engine, {
            facetId: this.facetId,
            conditions: parseDependsOn(this.dependsOn || {})
        });
    }
    generateCurrentValues() {
        const currentValues = [];
        for(let i = this.minValueInIndex; i <= this.numberOfIntervals; i++)currentValues.push(buildNumericRange({
            start: Math.round(i * this.scaleFactor * 100) / 100,
            end: Math.round((this.maxValueInIndex ?? this.numberOfIntervals) * 100) / 100,
            endInclusive: true
        }));
        return currentValues;
    }
    formatFacetValue(facetValue) {
        const maxValue = this.maxValueInIndex ?? this.numberOfIntervals;
        if (facetValue.start === maxValue) return this.bindings.i18n.t('stars-only', {
            count: facetValue.start
        });
        return this.bindings.i18n.t('stars-range', {
            value: facetValue.start,
            count: maxValue
        });
    }
    ratingContent(facetValue) {
        return html`<div class="flex items-center">
      ${renderRating({
            props: {
                i18n: this.bindings.i18n,
                numberOfTotalIcons: this.maxValueInIndex ?? this.numberOfIntervals,
                numberOfActiveIcons: facetValue.start,
                icon: this.icon
            }
        })}
      ${this.renderLabelText(facetValue)}
    </div>`;
    }
    renderHeader() {
        return renderFacetHeader({
            props: {
                i18n: this.bindings.i18n,
                label: this.label,
                onClearFilters: ()=>{
                    this.focusTarget.focusAfterSearch();
                    this.facet.deselectAll();
                },
                numberOfActiveValues: this.numberOfSelectedValues,
                isCollapsed: this.isCollapsed,
                headingLevel: this.headingLevel,
                onToggleCollapse: ()=>{
                    this.isCollapsed = !this.isCollapsed;
                },
                headerRef: (el)=>this.focusTarget.setTarget(el)
            }
        });
    }
    renderLabelText(facetValue) {
        return html`<span
      part="value-label"
      class="group-focus:text-primary group-hover:text-primary ml-1 flex items-center truncate ${'selected' === facetValue.state ? 'font-bold' : ''}"
    >
      ${when(facetValue.start === (this.maxValueInIndex ?? this.numberOfIntervals), ()=>html`<span>${this.bindings.i18n.t('only')}</span>`, ()=>html`${this.bindings.i18n.t('and-up')}`)}
    </span>`;
    }
    renderValue(facetValue, onClick) {
        const displayValue = this.formatFacetValue(facetValue);
        const isSelected = 'selected' === facetValue.state;
        return renderFacetValueLink({
            props: {
                displayValue,
                numberOfResults: facetValue.numberOfResults,
                isSelected,
                i18n: this.bindings.i18n,
                onClick
            }
        })(this.ratingContent(facetValue));
    }
    renderValuesContainer(children) {
        return renderFacetValuesGroup({
            props: {
                i18n: this.bindings.i18n,
                label: this.label
            }
        })(html`<ul class="mt-3" part="values">
      ${children}
    </ul>`);
    }
    renderValues() {
        return this.renderValuesContainer(this.valuesToRender.map((value)=>this.renderValue(value, ()=>this.facet.toggleSingleSelect(value))));
    }
    get valuesToRender() {
        return this.facet.state.values.filter((value)=>value.numberOfResults || 'idle' !== value.state);
    }
    render() {
        return html`${when(!this.searchStatusState.hasError && this.facet.state.enabled, ()=>{
            if (!this.searchStatusState.firstSearchExecuted) return renderFacetPlaceholder({
                props: {
                    numberOfValues: this.numberOfIntervals,
                    isCollapsed: this.isCollapsed
                }
            });
            if (!this.valuesToRender.length) return nothing;
            return renderFacetContainer()(html`${this.renderHeader()}
        ${when(!this.isCollapsed, ()=>this.renderValues())}`);
        })}`;
    }
    constructor(){
        super(), this.label = 'no-label', this.tabsIncluded = [], this.tabsExcluded = [], this.numberOfIntervals = 5, this.minValueInIndex = 1, this.icon = star, this.isCollapsed = false, this.headingLevel = 0, this.injectionDepth = 1000;
        new ValidatePropsController(this, ()=>({
                field: this.field,
                numberOfIntervals: this.numberOfIntervals,
                maxValueInIndex: this.maxValueInIndex,
                minValueInIndex: this.minValueInIndex,
                injectionDepth: this.injectionDepth,
                dependsOn: this.dependsOn
            }), AtomicRatingRangeFacet.propsSchema, false);
    }
}
AtomicRatingRangeFacet.propsSchema = new Schema({
    field: new StringValue({
        required: true,
        emptyAllowed: false
    }),
    numberOfIntervals: new NumberValue({
        min: 1
    }),
    maxValueInIndex: new NumberValue({
        min: 0,
        required: false
    }),
    minValueInIndex: new NumberValue({
        min: 0
    }),
    injectionDepth: new NumberValue({
        min: 0
    }),
    dependsOn: new RecordValue({
        options: {
            required: false
        }
    })
});
AtomicRatingRangeFacet.styles = [
    facet_common_tw_css,
    facet_value_checkbox_tw_css,
    atomic_rating_tw_css
];
_ts_decorate([
    decorators_js_state(),
    _ts_metadata("design:type", "u" < typeof Bindings ? Object : Bindings)
], AtomicRatingRangeFacet.prototype, "bindings", void 0);
_ts_decorate([
    decorators_js_state(),
    _ts_metadata("design:type", "u" < typeof Error ? Object : Error)
], AtomicRatingRangeFacet.prototype, "error", void 0);
_ts_decorate([
    bindStateToController('facet'),
    decorators_js_state(),
    _ts_metadata("design:type", "u" < typeof NumericFacetState ? Object : NumericFacetState)
], AtomicRatingRangeFacet.prototype, "facetState", void 0);
_ts_decorate([
    bindStateToController('searchStatus'),
    decorators_js_state(),
    _ts_metadata("design:type", "u" < typeof SearchStatusState ? Object : SearchStatusState)
], AtomicRatingRangeFacet.prototype, "searchStatusState", void 0);
_ts_decorate([
    bindStateToController('tabManager'),
    decorators_js_state(),
    _ts_metadata("design:type", "u" < typeof TabManagerState ? Object : TabManagerState)
], AtomicRatingRangeFacet.prototype, "tabManagerState", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'facet-id',
        type: String
    }),
    _ts_metadata("design:type", String)
], AtomicRatingRangeFacet.prototype, "facetId", void 0);
_ts_decorate([
    property({
        reflect: true,
        type: String
    })
], AtomicRatingRangeFacet.prototype, "label", void 0);
_ts_decorate([
    property({
        reflect: true,
        type: String
    }),
    _ts_metadata("design:type", String)
], AtomicRatingRangeFacet.prototype, "field", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'tabs-included',
        type: Array,
        converter: arrayConverter
    }),
    _ts_metadata("design:type", Array)
], AtomicRatingRangeFacet.prototype, "tabsIncluded", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'tabs-excluded',
        type: Array,
        converter: arrayConverter
    }),
    _ts_metadata("design:type", Array)
], AtomicRatingRangeFacet.prototype, "tabsExcluded", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'number-of-intervals',
        type: Number
    })
], AtomicRatingRangeFacet.prototype, "numberOfIntervals", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'max-value-in-index',
        type: Number
    }),
    _ts_metadata("design:type", Number)
], AtomicRatingRangeFacet.prototype, "maxValueInIndex", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'min-value-in-index',
        type: Number
    })
], AtomicRatingRangeFacet.prototype, "minValueInIndex", void 0);
_ts_decorate([
    property({
        reflect: true,
        type: String
    })
], AtomicRatingRangeFacet.prototype, "icon", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'is-collapsed',
        type: Boolean,
        converter: booleanConverter
    })
], AtomicRatingRangeFacet.prototype, "isCollapsed", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'heading-level',
        type: Number
    })
], AtomicRatingRangeFacet.prototype, "headingLevel", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'filter-facet-count',
        type: Boolean,
        converter: booleanConverter
    }),
    _ts_metadata("design:type", Boolean)
], AtomicRatingRangeFacet.prototype, "filterFacetCount", void 0);
_ts_decorate([
    property({
        reflect: true,
        attribute: 'injection-depth',
        type: Number
    })
], AtomicRatingRangeFacet.prototype, "injectionDepth", void 0);
_ts_decorate([
    mapProperty({
        attributePrefix: 'depends-on'
    }),
    _ts_metadata("design:type", "u" < typeof Record ? Object : Record)
], AtomicRatingRangeFacet.prototype, "dependsOn", void 0);
_ts_decorate([
    bindingGuard(),
    errorGuard(),
    _ts_metadata("design:type", Function),
    _ts_metadata("design:paramtypes", []),
    _ts_metadata("design:returntype", void 0)
], AtomicRatingRangeFacet.prototype, "render", null);
AtomicRatingRangeFacet = _ts_decorate([
    customElement('atomic-rating-range-facet'),
    bindings(),
    withTailwindStyles,
    _ts_metadata("design:type", Function),
    _ts_metadata("design:paramtypes", [])
], AtomicRatingRangeFacet);
export { AtomicRatingRangeFacet };
