/**
 * Copyright Aquera Inc 2023
 *
 * This source code is licensed under the BSD-3-Clause license found in the
 * LICENSE file in the root directory of this source tree.
 */
import { __decorate } from "tslib";
import { styles } from './nile-option.css';
import '../nile-icon';
import { classMap } from 'lit/directives/class-map.js';
import { customElement, property, query, state } from 'lit/decorators.js';
import { html } from 'lit';
import { watch } from '../internal/watch';
import NileElement from '../internal/nile-element';
import '../nile-checkbox';
/**
 * Nile icon component.
 *
 * @tag nile-option
 *
 */
/**
 * @summary Options define the selectable items within various form controls such as [select](/components/select).
 * @status stable
 *
 * @dependency nile-icon
 *
 * @slot - The option's label.
 * @slot prefix - Used to prepend an icon or similar element to the menu item.
 * @slot suffix - Used to append an icon or similar element to the menu item.
 *
 * @csspart checked-icon - The checked icon, an `<nile-icon>` element.
 * @csspart base - The component's base wrapper.
 * @csspart label - The option's label.
 * @csspart prefix - The container that wraps the prefix.
 * @csspart suffix - The container that wraps the suffix.
 */
let NileOption = class NileOption extends NileElement {
    constructor() {
        super(...arguments);
        this.current = false; // the user has keyed into the option, but hasn't selected it yet (shows a highlight)
        this.hasHover = false; // we need this because Safari doesn't honor :hover styles while dragging
        this.hidden = false; // the option is hidden
        this.isMultipleSelect = false;
        /**
         * The option's value. When selected, the containing form control will receive this value. The value must be unique
         * from other options in the same group. Values may not contain spaces, as spaces are used as delimiters when listing
         * multiple values.
         */
        this.value = '';
        this.showCheckbox = false;
        /** Draws the option in a disabled state, preventing selection. */
        this.disabled = false;
        /** Indicates whether the option is selected. */
        this.selected = false;
        /* used to pass group name to the option, so that grouped options can be shown */
        this.groupName = '';
        /* used to pass description to the option, so that description can be shown */
        this.description = '';
        this.isParentVirtualSelect = false;
        this.isDescriptionEnabled = false;
    }
    connectedCallback() {
        super.connectedCallback();
        this.setAttribute('role', 'option');
        this.setAttribute('aria-selected', 'false');
        this.checkIfMultipleSelect();
    }
    firstUpdated() {
        if (this.parentElement?.tagName === 'NILE-SELECT') {
            return;
        }
        this.isParentVirtualSelect = true;
        this.applyWidthToLabelContainer();
    }
    applyWidthToLabelContainer() {
        const hasPrefix = (this.prefixSlot?.assignedNodes({ flatten: true }) ?? []).length > 0;
        const hasSuffix = (this.suffixSlot?.assignedNodes({ flatten: true }) ?? []).length > 0;
        let totalWidth = 0;
        if (hasPrefix)
            totalWidth += 30;
        if (hasSuffix)
            totalWidth += 30;
        if (this.showCheckbox)
            totalWidth += 50;
        if (this.labelContainer) {
            this.labelContainer.style.width = `calc(100% - ${totalWidth}px)`;
        }
    }
    checkIfMultipleSelect() {
        // Find the closest parent 'nile-select' element
        const parentSelect = this.closest('nile-select');
        // Check if the parent has the 'multiple' attribute
        if (parentSelect && parentSelect.hasAttribute('multiple')) {
            if (parentSelect.hasAttribute('multiple') && parentSelect.getAttribute('multiple') === '') {
                this.isMultipleSelect = true;
            }
            else if (parentSelect.getAttribute('multiple') === 'true') {
                this.isMultipleSelect = true;
            }
            else {
                this.isMultipleSelect = false;
            }
        }
        else {
            this.isMultipleSelect = this.showCheckbox;
        }
    }
    updated(_changedProperties) {
        this.checkIfMultipleSelect();
    }
    handleDefaultSlotChange() {
        const textLabel = this.getTextLabel();
        // Ignore the first time the label is set
        if (typeof this.cachedTextLabel === 'undefined') {
            this.cachedTextLabel = textLabel;
            return;
        }
        // When the label changes, emit a slotchange event so parent controls see it
        if (textLabel !== this.cachedTextLabel) {
            this.cachedTextLabel = textLabel;
            this.emit('slotchange');
        }
    }
    handleMouseEnter() {
        this.hasHover = true;
    }
    handleMouseLeave() {
        this.hasHover = false;
    }
    handleDisabledChange() {
        this.setAttribute('aria-disabled', this.disabled ? 'true' : 'false');
    }
    handleSelectedChange() {
        this.setAttribute('aria-selected', this.selected ? 'true' : 'false');
    }
    handleValueChange() {
        // Ensure the value is a string. This ensures the next line doesn't error and allows framework users to pass numbers
        // instead of requiring them to cast the value to a string.
        if (typeof this.value !== 'string') {
            this.value = String(this.value);
        }
        // if (this.value.includes(' ')) {
        //   console.error(
        //     `Option values cannot include a space. All spaces have been replaced with underscores.`,
        //     this
        //   );
        //   this.value = this.value.replace(/ /g, '_');
        // }
    }
    /** Returns a plain text label based on the option's content. */
    getTextLabel() {
        // Search for a label element inside the component
        const labelElement = this.querySelector('label');
        // If a label element is found, return its text content
        if (labelElement) {
            return labelElement.textContent?.trim() ?? '';
        }
        // If no label element is found, return the existing behavior
        return (this.textContent ?? '').trim();
    }
    render() {
        return html `
      ${!this.hidden
            ? html ` <div
            part="base"
            class=${classMap({
                option: true,
                'option--single-select': !this.isMultipleSelect,
                'option--current': this.selected && !this.isMultipleSelect,
                'option--disabled': this.disabled,
                'option--selected': this.selected && !this.isMultipleSelect,
                'option--hover': this.hasHover,
            })}
            @mouseenter=${this.handleMouseEnter}
            @mouseleave=${this.handleMouseLeave}
          >

          ${this.isMultipleSelect ? html `<nile-checkbox part="checkbox" class="option--checkbox" .checked=${this.selected}></nile-checkbox>` : ''}

            <slot part="prefix" name="prefix" class="option__prefix"></slot>
              ${this.isDescriptionEnabled
                ? html `
                    <div
                      class="option__label-container"
                      part="option_label_container"
                    >
                      <slot
                        part="label"
                        class=${classMap({
                    'option__label': true,
                    'option__label-text-ellipsis': this.isParentVirtualSelect,
                })}
                        @slotchange=${this.handleDefaultSlotChange}
                      ></slot>
  
                      ${this.description
                    ? html `
                            <span
                              part="option_description"
                              class=${classMap({
                        option__description: true,
                        'text-ellipsis': this.isParentVirtualSelect,
                    })}
                            >
                              ${this.description}
                            </span>
                          `
                    : null}
                    </div>
                  `
                : html `
                    <slot
                      part="label"
                      class="option__label"
                      @slotchange=${this.handleDefaultSlotChange}
                    ></slot>
                  `}
  
              <slot part="suffix" name="suffix" class="option__suffix"></slot>
            </div>`
            : ''}
    `;
    }
};
NileOption.styles = styles;
__decorate([
    query('.option__label')
], NileOption.prototype, "defaultSlot", void 0);
__decorate([
    state()
], NileOption.prototype, "current", void 0);
__decorate([
    state()
], NileOption.prototype, "hasHover", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileOption.prototype, "hidden", void 0);
__decorate([
    state()
], NileOption.prototype, "isMultipleSelect", void 0);
__decorate([
    property({ reflect: true })
], NileOption.prototype, "value", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileOption.prototype, "showCheckbox", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileOption.prototype, "disabled", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], NileOption.prototype, "selected", void 0);
__decorate([
    property({ type: String, reflect: true, attribute: true })
], NileOption.prototype, "groupName", void 0);
__decorate([
    property({ type: String, reflect: true, attribute: true })
], NileOption.prototype, "description", void 0);
__decorate([
    query('slot[name="prefix"]')
], NileOption.prototype, "prefixSlot", void 0);
__decorate([
    query('slot[name="suffix"]')
], NileOption.prototype, "suffixSlot", void 0);
__decorate([
    query('.option__label-container')
], NileOption.prototype, "labelContainer", void 0);
__decorate([
    state()
], NileOption.prototype, "isParentVirtualSelect", void 0);
__decorate([
    property({ type: Boolean, reflect: true, attribute: true })
], NileOption.prototype, "isDescriptionEnabled", void 0);
__decorate([
    watch('disabled')
], NileOption.prototype, "handleDisabledChange", null);
__decorate([
    watch('selected')
], NileOption.prototype, "handleSelectedChange", null);
__decorate([
    watch('value')
], NileOption.prototype, "handleValueChange", null);
NileOption = __decorate([
    customElement('nile-option')
], NileOption);
export { NileOption };
export default NileOption;
//# sourceMappingURL=nile-option.js.map