// #region Imports
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") 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;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { HTMLElementEventEmitter } from '@breadstone/mosaik-elements';
import { CssAspectRatio, CssLength } from '@breadstone/mosaik-themes';
import { RendererServiceLocator } from '../../../../Dom/Renderer';
import { Emit } from '../../../../events/Decorators/EmitDecorator';
import { Dimensionable } from '../../../Behaviors/Dimensionable';
import { Disableable } from '../../../Behaviors/Disableable';
import { Themeable } from '../../../Behaviors/Themeable';
import { Variantable } from '../../../Behaviors/Variantable';
import { Attribute } from '../../../Decorators/AttributeDecorator';
import { Component } from '../../../Decorators/ComponentDecorator';
import { Property } from '../../../Decorators/PropertyDecorator';
import { Watch } from '../../../Decorators/WatchDecorator';
import { ImageFit } from '../../../Types/ImageFit';
import { ImageLegendPosition } from '../../../Types/ImageLegendPosition';
import { CustomElement } from '../../Abstracts/CustomElement';
import { TextElement } from '../../Primitives/Text/TextElement';
import { ProgressRingElement } from '../../Ranges/ProgressRing/ProgressRingElement';
import { IconElement } from '../Icon/IconElement';
import { imageElementTemplate } from './ImageElementTemplate';
import { imageElementCosmopolitanStyle } from './Themes/ImageElement.Cosmopolitan';
import { imageElementJoyStyle } from './Themes/ImageElement.Joy';
import { imageElementMemphisStyle } from './Themes/ImageElement.Memphis';
// #endregion
/**
 * Image - A responsive image container with advanced loading states and layout control.
 *
 * Provides comprehensive image handling with loading indicators, error states, aspect ratio control,
 * and flexible content placement. Supports various fit modes, lazy loading, and accessibility features.
 * Includes built-in placeholder states and legend positioning for rich media presentation.
 *
 * @name ImageElement
 * @element mosaik-image
 * @category Media
 *
 * @slot - Default content overlaid on the image
 * @slot empty - Content shown when no image source is provided
 * @slot failed - Content displayed when image loading fails
 * @slot pending - Content shown while image is loading
 * @slot legend - Caption or description content positioned around the image
 *
 * @csspart image - The main image element container
 * @csspart thumbnail - Blurred low-resolution placeholder image displayed during loading
 * @csspart placeholder - Container for loading, error, and empty states
 * @csspart legend - Caption or description container
 * @csspart content - Overlay content container
 *
 * @cssprop {String} --image-aspect-ratio - Aspect ratio constraint for the image container
 * @cssprop {String} --image-object-fit - How the image fits within its container (cover, contain, fill, etc.)
 * @cssprop {String} --image-border-radius - Border radius applied to the image
 * @cssprop {Color} --image-placeholder-color - Background color for placeholder states
 * @cssprop {String} --image-legend-position - Position of the legend relative to image
 * @cssprop {String} --image-thumbnail-blur - Blur radius applied to the thumbnail placeholder
 *
 * @dependency TextElement - For legend text rendering
 * @dependency ProgressRingElement - For loading state indicator
 * @dependency IconElement - For error and empty state icons
 *
 * @example
 * ```html
 * <!-- Basic image -->
 * <mosaik-image src="photo.jpg" alt="Landscape photo"></mosaik-image>
 *
 * <!-- Image with ratio and fit mode -->
 * <mosaik-image
 *   src="portrait.jpg"
 *   ratio="4/3"
 *   fit="cover"
 *   alt="Portrait photo">
 * </mosaik-image>
 *
 * <!-- Image with legend and thumbnail placeholder -->
 * <mosaik-image
 *   src="high-res.jpg"
 *   thumbnail-src="low-res-thumb.jpg"
 *   legend-position="bottom">
 *   <span slot="legend">Photo caption</span>
 * </mosaik-image>
 * ```
 *
 * @fires imageLoaded {ImageLoadedEvent} - Emitted when image successfully loads
 * @fires imageFailed {ImageFailedEvent} - Emitted when image loading fails
 *
 * @public
 */
let ImageElement = class ImageElement extends Themeable(Disableable(Variantable(Dimensionable(CustomElement)))) {
    // #region Fields
    _imageLoaded;
    _imageFailed;
    _alt;
    _src;
    _srcset;
    _state;
    _fit;
    _thumbnailSrc;
    _showFailed;
    _showEmpty;
    _showPending;
    _legend;
    _legendPosition;
    _ratio;
    // #endregion
    // #region Ctor
    /**
     * @public
     */
    constructor() {
        super();
        this._alt = '';
        this._src = '';
        this._srcset = '';
        this._state = 'done';
        this._fit = ImageFit.Cover;
        this._thumbnailSrc = '';
        this._showFailed = false;
        this._showEmpty = false;
        this._showPending = false;
        this._legend = '';
        this._legendPosition = ImageLegendPosition.None;
        this._ratio = 'auto';
        this._imageLoaded = new HTMLElementEventEmitter(this, 'imageLoaded');
        this._imageFailed = new HTMLElementEventEmitter(this, 'imageFailed');
    }
    // #endregion
    // #region Properties
    /**
     * Returns the `is` property.
     * The `is` property represents natural name of this element.
     *
     * @public
     * @static
     * @readonly
     */
    static get is() {
        return 'mosaik-image';
    }
    /**
     * Gets or sets the `alt` property.
     *
     * @public
     * @attr
     */
    get alt() {
        return this._alt;
    }
    set alt(value) {
        if (this._alt !== value) {
            this._alt = value;
            this.requestUpdate('alt');
        }
    }
    /**
     * Gets or sets the `src` property.
     *
     * @public
     * @attr
     */
    get src() {
        return this._src;
    }
    set src(value) {
        if (this._src !== value) {
            this._src = value;
            this.requestUpdate('src');
        }
    }
    /**
     * Gets or sets the `srcset` property.
     *
     * @public
     * @attr
     */
    get srcset() {
        return this._srcset;
    }
    set srcset(value) {
        if (this._srcset !== value) {
            this._srcset = value;
            this.requestUpdate('srcset');
        }
    }
    /**
     * Gets or sets the `showFailed` property.
     *
     * @public
     */
    get showFailed() {
        return this._showFailed;
    }
    set showFailed(value) {
        if (this._showFailed !== value) {
            this._showFailed = value;
            this.requestUpdate('showFailed');
        }
    }
    /**
     * Gets or sets the `showEmpty` property.
     *
     * @public
     */
    get showEmpty() {
        return this._showEmpty;
    }
    set showEmpty(value) {
        if (this._showEmpty !== value) {
            this._showEmpty = value;
            this.requestUpdate('showEmpty');
        }
    }
    /**
     * Gets or sets the `showEmpty` property.
     *
     * @public
     */
    get showPending() {
        return this._showPending;
    }
    set showPending(value) {
        if (this._showPending !== value) {
            this._showPending = value;
            this.requestUpdate('showPending');
        }
    }
    /**
     * Gets or sets the `fit` property.
     *
     * @public
     * @attr
     */
    get fit() {
        return this._fit;
    }
    set fit(value) {
        if (this._fit !== value) {
            this._fit = value;
            this.requestUpdate('fit');
        }
    }
    /**
     * Gets or sets the `thumbnailSrc` property.
     * When set, a low-resolution blurred version of the image is displayed as a placeholder
     * while the full image loads. The thumbnail fades out once the main image is ready.
     * The default value is an empty string, which means no thumbnail is displayed.
     *
     * @public
     * @attr
     */
    get thumbnailSrc() {
        return this._thumbnailSrc;
    }
    set thumbnailSrc(value) {
        if (this._thumbnailSrc !== value) {
            this._thumbnailSrc = value;
            this.requestUpdate('thumbnailSrc');
        }
    }
    /**
     * Gets or sets the `legend` property.
     *
     * @public
     * @attr
     */
    get legend() {
        return this._legend;
    }
    set legend(value) {
        if (this._legend !== value) {
            this._legend = value;
            this.requestUpdate('legend');
        }
    }
    /**
     * Gets or sets the `legendPosition` property.
     *
     * @public
     * @attr
     */
    get legendPosition() {
        return this._legendPosition;
    }
    set legendPosition(value) {
        if (this._legendPosition !== value) {
            this._legendPosition = value;
            this.requestUpdate('legendPosition');
        }
    }
    /**
      * Returns the `state` property.
      *
      * @public
      * @readonly
      */
    get state() {
        return this._state;
    }
    set state(value) {
        if (this._state !== value) {
            this._state = value;
            this.requestUpdate('state');
        }
    }
    /**
     * Gets or sets the `ratio` property.
     *
     * @public
     * @attr
     */
    get ratio() {
        return this._ratio;
    }
    set ratio(value) {
        if (this._ratio !== value) {
            this._ratio = value;
            this.requestUpdate('ratio');
        }
    }
    /**
     * Called when the image is loaded.
     * Provides reference to `IEventDetail` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get imageLoaded() {
        return this._imageLoaded;
    }
    /**
     * Called when the image load is failed.
     * Provides reference to `IEventDetail` as event detail.
     *
     * @public
     * @readonly
     * @eventProperty
     */
    get imageFailed() {
        return this._imageFailed;
    }
    // #endregion
    // #region Methods
    /**
     * @protected
     */
    onWidthPropertyChanged(_prev, next) {
        RendererServiceLocator.current.setStyle(this, 'min-width', next);
        RendererServiceLocator.current.setStyle(this, 'width', next);
    }
    /**
     * @protected
     */
    onHeightPropertyChanged(_prev, next) {
        RendererServiceLocator.current.setStyle(this, 'min-height', next);
        RendererServiceLocator.current.setStyle(this, 'height', next);
    }
    /**
     * @protected
     */
    onSrcPropertyChanged(_prev, next) {
        if (next) {
            this.state = 'pending';
        }
    }
    /**
     * @protected
     */
    onRatioPropertyChanged(_prev, next) {
        if (next !== undefined) {
            RendererServiceLocator.current.setStyle(this, '--image-aspect-ratio', next);
        }
        else {
            RendererServiceLocator.current.removeStyle(this, '--image-aspect-ratio');
        }
    }
    /**
     * @template
     * @protected
     */
    onImageError() {
        this.state = 'failed';
        this._imageFailed.emit();
    }
    /**
     * @template
     * @protected
     */
    onImageLoad() {
        this.state = 'done';
        this._imageLoaded.emit();
    }
};
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ImageElement.prototype, "alt", null);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ImageElement.prototype, "src", null);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ImageElement.prototype, "srcset", null);
__decorate([
    Property({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ImageElement.prototype, "showFailed", null);
__decorate([
    Property({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ImageElement.prototype, "showEmpty", null);
__decorate([
    Property({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ImageElement.prototype, "showPending", null);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ImageElement.prototype, "fit", null);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ImageElement.prototype, "thumbnailSrc", null);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ImageElement.prototype, "legend", null);
__decorate([
    Attribute({ type: ImageLegendPosition }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ImageElement.prototype, "legendPosition", null);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ImageElement.prototype, "state", null);
__decorate([
    Attribute({ type: String }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ImageElement.prototype, "ratio", null);
__decorate([
    Emit({ eventName: 'imageLoaded' }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], ImageElement.prototype, "imageLoaded", null);
__decorate([
    Emit({ eventName: 'imageFailed' }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [])
], ImageElement.prototype, "imageFailed", null);
__decorate([
    Watch('width'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object]),
    __metadata("design:returntype", void 0)
], ImageElement.prototype, "onWidthPropertyChanged", null);
__decorate([
    Watch('height'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object]),
    __metadata("design:returntype", void 0)
], ImageElement.prototype, "onHeightPropertyChanged", null);
__decorate([
    Watch('src'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", void 0)
], ImageElement.prototype, "onSrcPropertyChanged", null);
__decorate([
    Watch('ratio'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", void 0)
], ImageElement.prototype, "onRatioPropertyChanged", null);
ImageElement = __decorate([
    Component({
        selector: 'mosaik-image',
        template: imageElementTemplate,
        themes: {
            joy: imageElementJoyStyle,
            memphis: imageElementMemphisStyle,
            cosmopolitan: imageElementCosmopolitanStyle
        },
        imports: [
            TextElement,
            IconElement,
            ProgressRingElement
        ]
    }),
    __metadata("design:paramtypes", [])
], ImageElement);
export { ImageElement };
//# sourceMappingURL=ImageElement.js.map