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;
};
import { UmbFocalPointChangeEvent } from './focalpoint-change.event.js';
import { isCentered } from './utils.js';
import { drag } from '../../../../../external/uui/index.js';
import { clamp } from '../../../../core/utils/index.js';
import { css, customElement, classMap, eventOptions, ifDefined, html, nothing, state, property, query, } from '../../../../../external/lit/index.js';
import { UmbLitElement } from '../../../../core/lit-element/index.js';
let UmbImageCropperFocusSetterElement = class UmbImageCropperFocusSetterElement extends UmbLitElement {
    constructor() {
        super(...arguments);
        this._isDraggingGridHandle = false;
        this._coords = { x: 0, y: 0 };
        this.#focalPoint = { left: 0.5, top: 0.5 };
        this.hideFocalPoint = false;
        this.disabled = false;
        this.#DOT_RADIUS = 8;
    }
    set focalPoint(value) {
        this.#focalPoint = value;
        this.#setFocalPointStyle(this.#focalPoint.left, this.#focalPoint.top);
        this.#onFocalPointUpdated();
    }
    get focalPoint() {
        return this.#focalPoint;
    }
    #focalPoint;
    #DOT_RADIUS;
    update(changedProperties) {
        super.update(changedProperties);
        if (changedProperties.has('src')) {
            if (this.src) {
                this.#initializeImage();
            }
        }
    }
    firstUpdated(_changedProperties) {
        super.firstUpdated(_changedProperties);
        this.style.setProperty('--dot-radius', `${this.#DOT_RADIUS}px`);
    }
    async #initializeImage() {
        await this.updateComplete; // Wait for the @query to be resolved
        if (!this.hideFocalPoint) {
            this.#setFocalPointStyle(this.focalPoint.left, this.focalPoint.top);
        }
        this.imageElement.onload = () => {
            if (!this.imageElement || !this.wrapperElement)
                return;
            const imageAspectRatio = this.imageElement.naturalWidth / this.imageElement.naturalHeight;
            const hostRect = this.getBoundingClientRect();
            const image = this.imageElement.getBoundingClientRect();
            if (image.width > hostRect.width) {
                this.imageElement.style.width = '100%';
            }
            if (image.height > hostRect.height) {
                this.imageElement.style.height = '100%';
            }
            this.#resetCoords();
            this.imageElement.style.aspectRatio = `${imageAspectRatio}`;
            this.wrapperElement.style.aspectRatio = `${imageAspectRatio}`;
        };
    }
    #onFocalPointUpdated() {
        if (this.#isCentered(this.#focalPoint)) {
            this.#resetCoords();
        }
    }
    #setFocalPoint(x, y, width, height) {
        const left = clamp(x / width, 0, 1);
        const top = clamp(y / height, 0, 1);
        const focalPoint = { left, top };
        this.dispatchEvent(new UmbFocalPointChangeEvent(focalPoint));
    }
    #setFocalPointStyle(left, top) {
        if (!this.focalPointElement)
            return;
        this.focalPointElement.style.left = `calc(${left * 100}% - ${this.#DOT_RADIUS}px)`;
        this.focalPointElement.style.top = `calc(${top * 100}% - ${this.#DOT_RADIUS}px)`;
    }
    #isCentered(focalPoint) {
        if (!this.focalPoint)
            return;
        return isCentered(focalPoint);
    }
    #resetCoords() {
        if (!this.imageElement)
            return;
        // Init x and y coords from half of rendered image size, which is equavalient to focal point { left: 0.5, top: 0.5 }.
        this._coords.x = this.imageElement?.clientWidth / 2;
        this._coords.y = this.imageElement.clientHeight / 2;
    }
    _handleGridDrag(event) {
        if (this.disabled || this.hideFocalPoint)
            return;
        if (event.button !== 0) {
            // This is not a primary mouse button click, so lets not do anything.
            return;
        }
        const grid = this.wrapperElement;
        const handle = this.focalPointElement;
        if (!grid)
            return;
        const { width, height } = grid.getBoundingClientRect();
        handle?.focus();
        event.preventDefault();
        event.stopPropagation();
        this._isDraggingGridHandle = true;
        drag(grid, {
            onMove: (x, y) => {
                // check if coordinates are not NaN (can happen when dragging outside of the grid)
                if (isNaN(x) || isNaN(y))
                    return;
                this._coords.x = x;
                this._coords.y = y;
                this.#setFocalPoint(x, y, width, height);
            },
            onStop: () => (this._isDraggingGridHandle = false),
            initialEvent: event,
        });
    }
    #changeFocalPoint(event) {
        if (this.disabled || this.hideFocalPoint)
            return;
        if (event.button !== 0) {
            // This is not a primary mouse button click, so lets not do anything.
            return;
        }
        const grid = this.wrapperElement;
        const handle = this.focalPointElement;
        if (!grid)
            return;
        handle?.focus();
        const dims = grid.getBoundingClientRect();
        const defaultView = grid.ownerDocument.defaultView;
        const { width, height } = grid.getBoundingClientRect();
        const offsetX = dims.left + defaultView.scrollX;
        const offsetY = dims.top + defaultView.scrollY;
        const x = event.pageX - offsetX;
        const y = event.pageY - offsetY;
        this.#setFocalPoint(x, y, width, height);
    }
    #handleGridKeyDown(event) {
        if (this.disabled || this.hideFocalPoint)
            return;
        const increment = event.shiftKey ? 1 : 10;
        const grid = this.wrapperElement;
        if (!grid)
            return;
        const { width, height } = grid.getBoundingClientRect();
        if (event.key === 'ArrowLeft') {
            event.preventDefault();
            this._coords.x = clamp(this._coords.x - increment, 0, width);
            this.#setFocalPoint(this._coords.x, this._coords.y, width, height);
        }
        if (event.key === 'ArrowRight') {
            event.preventDefault();
            this._coords.x = clamp(this._coords.x + increment, 0, width);
            this.#setFocalPoint(this._coords.x, this._coords.y, width, height);
        }
        if (event.key === 'ArrowUp') {
            event.preventDefault();
            this._coords.y = clamp(this._coords.y - increment, 0, height);
            this.#setFocalPoint(this._coords.x, this._coords.y, width, height);
        }
        if (event.key === 'ArrowDown') {
            event.preventDefault();
            this._coords.y = clamp(this._coords.y + increment, 0, height);
            this.#setFocalPoint(this._coords.x, this._coords.y, width, height);
        }
    }
    render() {
        if (!this.src)
            return nothing;
        return html `
			<div
				id="wrapper"
				@click=${this.#changeFocalPoint}
				@mousedown=${this._handleGridDrag}
				@touchstart=${this._handleGridDrag}>
				<img id="image" @keydown=${() => nothing} src=${this.src} alt="" />
				<span
					id="focal-point"
					class=${classMap({ 'focal-point--dragging': this._isDraggingGridHandle, hidden: this.hideFocalPoint })}
					tabindex=${ifDefined(this.disabled ? undefined : '0')}
					aria-label=${this.localize.term('general_focalPoint')}
					@keydown=${this.#handleGridKeyDown}>
				</span>
			</div>
		`;
    }
    static { this.styles = css `
		:host {
			display: flex;
			width: 100%;
			height: 100%;
			position: relative;
			user-select: none;
			background-color: var(--uui-color-surface);
			outline: 1px solid var(--uui-color-border);
		}
		/* Wrapper is used to make the focal point position responsive to the image size */
		#wrapper {
			position: relative;
			display: flex;
			margin: auto;
			max-width: 100%;
			max-height: 100%;
			box-sizing: border-box;
			forced-color-adjust: none;
		}
		:host(:not([hidefocalpoint])) #wrapper {
			cursor: crosshair;
		}
		#image {
			margin: auto;
			position: relative;
			max-width: 100%;
			max-height: 100%;
		}
		#focal-point {
			content: '';
			display: block;
			position: absolute;
			width: calc(2 * var(--dot-radius));
			height: calc(2 * var(--dot-radius));
			top: 0;
			box-shadow:
				rgba(0, 0, 0, 0.25) 0px 0px 0px 1px,
				inset rgba(0, 0, 0, 0.25) 0px 0px 0px 1px;
			border: solid 2px white;
			border-radius: 50%;
			pointer-events: none;
			transition: 150ms transform;
			box-sizing: inherit;
		}
		.focal-point--dragging {
			cursor: none;
			transform: scale(1.5);
		}
		#focal-point.hidden {
			display: none;
		}
	`; }
};
__decorate([
    query('#image')
], UmbImageCropperFocusSetterElement.prototype, "imageElement", void 0);
__decorate([
    query('#wrapper')
], UmbImageCropperFocusSetterElement.prototype, "wrapperElement", void 0);
__decorate([
    query('#focal-point')
], UmbImageCropperFocusSetterElement.prototype, "focalPointElement", void 0);
__decorate([
    state()
], UmbImageCropperFocusSetterElement.prototype, "_isDraggingGridHandle", void 0);
__decorate([
    state()
], UmbImageCropperFocusSetterElement.prototype, "_coords", void 0);
__decorate([
    property({ attribute: false })
], UmbImageCropperFocusSetterElement.prototype, "focalPoint", null);
__decorate([
    property({ type: Boolean })
], UmbImageCropperFocusSetterElement.prototype, "hideFocalPoint", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], UmbImageCropperFocusSetterElement.prototype, "disabled", void 0);
__decorate([
    property({ type: String })
], UmbImageCropperFocusSetterElement.prototype, "src", void 0);
__decorate([
    eventOptions({ passive: false })
], UmbImageCropperFocusSetterElement.prototype, "_handleGridDrag", null);
UmbImageCropperFocusSetterElement = __decorate([
    customElement('umb-image-cropper-focus-setter')
], UmbImageCropperFocusSetterElement);
export { UmbImageCropperFocusSetterElement };
