import { Host, h } from "@stencil/core";
import { cls, getId, isEmpty } from "../../utils/helpers";
import Time from "../../utils/time";
import { Lang } from "../../services/lang";
export class XTimepicker {
    constructor() {
        /**
         * Element ID for internal reference
         */
        this.inputId = getId('textarea');
        this.label = undefined;
        this.name = undefined;
        this.info = undefined;
        this.loading = undefined;
        this.cleanable = undefined;
        this.required = undefined;
        this.now = undefined;
        this.width = undefined;
        this.value = '';
        this.isValid = true;
        this.isFocused = undefined;
        this.isLoading = undefined;
        this.isDisabled = undefined;
        this.isVisible = undefined;
        this.hourHandAngle = 0;
        this.minuteHandAngle = 0;
        this.draggingHand = undefined;
        this.timeSelected = new Time();
    }
    /**
     * Watch changes in value property
     */
    watchValue(value) {
        var _a;
        this.timeSelected.parse(value);
        this.calculateAngleFromTime();
        this.internals.setFormValue(this.timeSelected.toString());
        this.el.dispatchEvent(new InputEvent('input', { bubbles: false }));
        this.formValidateCallback(true);
        (_a = this.internals.form) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new InputEvent('input', { bubbles: false }));
    }
    /**
     * This is called when the 'disabled' attribute of the element or or an ancestor <fieldset> is updated
     *
     * @param disabled
     */
    formDisabledCallback(disabled) {
        this.isDisabled = disabled;
    }
    /**
     * This is called when the parent/owner form is reset
     */
    formResetCallback() {
        this.internals.setFormValue('');
    }
    /**
     * This is called when the input is validated
     */
    formValidateCallback(dispatchValidation) {
        if (this.required && isEmpty(this.value)) {
            this.internals.setValidity({ valueMissing: true }, Lang.get('fields.validation.value-missing'));
        }
        else {
            this.internals.setValidity({});
        }
        if (dispatchValidation) {
            this.isValid = this.internals.validity.valid;
            this.onValidateInputEvent.emit(this.internals);
        }
    }
    /**
     * This is called on component will load
     */
    componentWillLoad() {
        if (isEmpty(this.value)) {
            if (this.now) {
                this.timeSelected = Time.now();
            }
            this.value = this.timeSelected.toString();
        }
    }
    /**
     * This is called on component did load
     */
    componentDidLoad() {
        this.clock.addEventListener('mousedown', this.onDragStart.bind(this));
        this.clock.addEventListener('mousemove', this.onDragMove.bind(this));
        this.clock.addEventListener('mouseup', this.onDragEnd.bind(this));
        this.clock.addEventListener('touchstart', this.onDragStart.bind(this));
        this.clock.addEventListener('touchmove', this.onDragMove.bind(this));
        this.clock.addEventListener('touchend', this.onDragEnd.bind(this));
        this.timeSelected.parse(this.value);
        setTimeout(() => {
            this.calculateAngleFromTime();
            this.formValidateCallback();
        }, 0);
    }
    /**
     * Set element value by event
     *
     * @param event
     */
    onInput(event) {
        const input = event.target;
        console.log(input.value, parseInt(input.value));
        if (input.classList.contains('hour-input')) {
            this.timeSelected.setPeriodHour(parseInt(input.value));
        }
        if (input.classList.contains('min-input')) {
            this.timeSelected.setMinute(parseInt(input.value));
        }
        if (input.classList.contains('period-input')) {
            this.timeSelected.setPeriodHour(this.timeSelected.hour, input.value);
        }
        this.value = this.timeSelected.toString();
    }
    /**
     * Set element value by keyboard event
     */
    onKeydownInput(event) {
        const value = parseInt(event.target.value);
        const max = parseInt(event.target.max);
        const input = event.target;
        if (!['ArrowUp', 'ArrowDown'].includes(event.key)) {
            return;
        }
        if (event.key === 'ArrowUp') {
            if (value < max) {
                input.value = (value + 1).toString().padStart(2, '0');
            }
            else {
                input.value = input.classList.contains('hour-input') ? '01' : '00';
            }
        }
        if (event.key === 'ArrowDown') {
            if (input.classList.contains('hour-input') ? value > 1 : value > 0) {
                input.value = (value - 1).toString().padStart(2, '0');
            }
            else {
                input.value = max.toString().padStart(2, '0');
            }
        }
        input.dispatchEvent(new InputEvent('input'));
    }
    /**
     * This called on input field is unfocused
     */
    onBlurInput(e) {
        const input = e.target;
        if (input.classList.contains('hour-input')) {
            this.hourHand.classList.remove('focus');
        }
        if (input.classList.contains('min-input')) {
            this.minuteHand.classList.remove('focus');
        }
        this.blurTimeout = setTimeout(() => {
            this.isFocused = false;
            this.isVisible = false;
            this.formValidateCallback(true);
        }, 50);
    }
    /**
     * This called on input field is focused
     */
    onFocusInput(e) {
        clearTimeout(this.blurTimeout);
        this.isFocused = true;
        this.isVisible = true;
        const input = e.target;
        if (input.classList.contains('hour-input')) {
            this.hourHand.classList.add('focus');
        }
        if (input.classList.contains('min-input')) {
            this.minuteHand.classList.add('focus');
        }
    }
    /**
     * On drag start event
     */
    onDragStart(event) {
        let target = event.target;
        if (event instanceof TouchEvent) {
            event.preventDefault();
            target = document.elementFromPoint(event.touches[0].clientX, event.touches[0].clientY);
        }
        if (target.tagName === 'SPAN') {
            target = target.parentElement;
        }
        if (target === this.hourHand || target === this.minuteHand) {
            this.draggingHand = target;
        }
        else {
            this.draggingHand = null;
        }
    }
    /**
     * On drag move event
     */
    onDragMove(event) {
        if (this.draggingHand && [this.hourHand, this.minuteHand].includes(this.draggingHand)) {
            if (event instanceof TouchEvent) {
                event.preventDefault();
            }
            const rect = this.clock.getBoundingClientRect();
            const centerX = rect.left + rect.width / 2;
            const centerY = rect.top + rect.height / 2;
            const deltaX = (event instanceof TouchEvent ? event.touches[0] : event).clientX - centerX;
            const deltaY = (event instanceof TouchEvent ? event.touches[0] : event).clientY - centerY;
            let angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;
            angle = (angle + 360) % 360;
            if (this.draggingHand === this.minuteHand) {
                this.timeSelected.setMinute(Math.round(angle / 6) % 60);
            }
            else if (this.draggingHand === this.hourHand) {
                this.timeSelected.setPeriodHour(Math.round(angle / 30) % 12 || 12);
            }
            this.value = this.timeSelected.toString();
        }
    }
    /**
     * On drag end event
     */
    onDragEnd() {
        this.draggingHand = null;
    }
    /**
     * Clears the input value
     */
    clearInput() {
        this.timeSelected.setPeriodHour(0, 'am');
        this.timeSelected.setMinute(0);
        this.value = this.timeSelected.toString();
    }
    /**
     * Handle hour button click
     */
    handleHourClick(hour) {
        this.timeSelected.setPeriodHour(hour);
        this.value = this.timeSelected.toString();
    }
    /**
     * Handle minute button click
     */
    handleMinuteClick(min) {
        this.timeSelected.setMinute(min);
        this.value = this.timeSelected.toString();
    }
    /**
     * Get hour position styles
     */
    getHourPosition(hour) {
        const angle = (hour - 3) * (Math.PI / 6);
        const x = 50 + 38 * Math.cos(angle);
        const y = 50 + 38 * Math.sin(angle);
        return {
            left: `${x}%`,
            top: `${y}%`,
        };
    }
    /**
     * Calculate the hand angle from the time
     */
    calculateAngleFromTime() {
        this.hourHandAngle = this.timeSelected.hour * 30;
        this.minuteHandAngle = this.timeSelected.minute * 6;
    }
    /**
     * Get tick position styles
     */
    getTickPosition(i) {
        const angle = (i - 15) * 6 * (Math.PI / 180);
        const x = 50 + 50 * Math.cos(angle);
        const y = 50 + 50 * Math.sin(angle);
        return {
            left: `${x}%`,
            top: `${y}%`,
            transform: `translate(-50%, -50%) rotate(${i * 6}deg)`,
        };
    }
    /**
     * Render component
     */
    render() {
        return h(Host, { key: 'b1dc8005a757de3b12a874c40631dd374a987ba7', "data-for": this.name, tabindex: "0", onFocus: (e) => this.onFocusInput(e), onBlur: (e) => this.onBlurInput(e), style: { maxWidth: this.width } }, h("div", { key: '2db6e5e6a2c045e576636871c0d79ce5e0a34bae', class: cls({
                "input-container": true,
                "focus": this.isFocused,
                "loading": this.loading || this.isLoading,
                "disabled": this.isDisabled,
                "required": this.required,
                "invalid": !this.isValid
            }) }, h("div", { key: '1c45e0f4b69ebbbe2db2c61baca8228a02885c97', class: "indicator" }, h("slot", { key: '4c8ae11a66729f35ee2598baba79d9da3fb5d2fb', name: "indicator" })), h("div", { key: '202c6cfa825d9efd34a1a0032a755315c930dd7e', class: "separator" }), h("div", { key: '1126ceec5097546bcafaef3474a4c0c847e6d8d6', class: "wrap" }, this.label && h("label", { key: 'ddc7e59af7f1f42bac639905c6be633bdfe249a9', htmlFor: `min-${this.inputId}` }, this.label), h("div", { key: '77cdffba148483c72e67ebedbd462ebbd0e0a71d' }, h("input", { key: '8a90f2cb4c5446d01bfe55703bdedab3e9f2aeaa', class: "hour-input", id: `hour-${this.inputId}`, type: "tel", placeholder: "00", max: 12, maxlength: 2, disabled: this.isDisabled || this.isLoading, value: Number.isNaN(this.timeSelected.hour) ? null : this.timeSelected.getPeriodHour().toString().padStart(2, '0'), onInput: (e) => this.onInput(e), onKeyDown: (e) => this.onKeydownInput(e), onFocus: (e) => this.onFocusInput(e), onBlur: (e) => this.onBlurInput(e) }), h("span", { key: '1833f6b3b023c4619ad0b0ca0ae623e80b00add7' }, ":"), h("input", { key: '7d7b41fc6df0eadb9947a5b9aa4d49926465bb41', class: "min-input", id: `min-${this.inputId}`, type: "tel", placeholder: "00", max: 59, maxlength: 2, disabled: this.isDisabled || this.isLoading, value: Number.isNaN(this.timeSelected.minute) ? null : this.timeSelected.minute.toString().padStart(2, '0'), onInput: (e) => this.onInput(e), onKeyDown: (e) => this.onKeydownInput(e), onFocus: (e) => this.onFocusInput(e), onBlur: (e) => this.onBlurInput(e) }), h("select", { key: 'b28751065cb60a2b67779a1d0d491f86ea146bed', class: "period-input", id: `period-${this.inputId}`, disabled: this.isDisabled || this.isLoading, onInput: (e) => this.onInput(e), onFocus: (e) => this.onFocusInput(e), onBlur: (e) => this.onBlurInput(e) }, h("option", { key: '1c169c440cb2cbf791f1d035ec46e0b6724eb640', value: "am", selected: this.timeSelected.getPeriod() === 'am' }, "AM"), h("option", { key: '1a8e278701f643e130a0591add1ba54b9d6eb5aa', value: "pm", selected: this.timeSelected.getPeriod() === 'pm' }, "PM")))), this.loading && h("div", { key: 'cb63b0d1630bf7bd5fbfaf4a06d9e9d37c1d8ba6', class: "loading-indicator" }), h("div", { key: '00c60e76fc225ca10dd6bbb9524a697a3d74dd5a', class: "buttons" }, this.cleanable && h("x-button", { key: 'b152fe8d4854e2c397065e11af823cde809fc43b', icon: "backclear", onClick: () => this.clearInput() }), h("slot", { key: '2dd80f560fa6d043bf231085bfcf508fbb9f2019', name: "buttons" })), this.info && h("div", { key: '5a0f143ce7938865f2951f8edfe283ace7b5bff7', class: "info" }, h("x-tooltip", { key: 'd3066eaa395b7780b339a9fd59b593db9319bc6c', content: this.info }, h("x-icon", { key: '59a7a33888a76863df40649386bc3adc1a0dadd7', name: "info" }))), h("slot", { key: 'ad30591338252cf5f1059ed2a05fe0eec982f874' })), h("div", { key: '476fd2f841090419592ada75c218535f9227ea00', class: cls('timepicker', {
                'active': this.isVisible,
            }) }, h("div", { key: 'c7a07d9f55a6a650e5026b61048e6d1836d0b162', class: "arrow" }), h("div", { key: 'e190c22c781719848fd514dddea7474741e93f2c', class: cls('clock', {
                'dragging': this.draggingHand,
            }), ref: el => this.clock = el }, [...Array(12).keys()].map(i => {
            const hour = i + 1;
            return h("button", { type: "button", class: "hour", style: this.getHourPosition(hour), onClick: () => this.handleHourClick(hour) }, hour);
        }), [...Array(60).keys()].map(i => {
            return h("button", { type: "button", class: cls(i % 5 === 0 ? 'hour-tick' : 'min-tick'), style: this.getTickPosition(i), onClick: () => this.handleMinuteClick(i) });
        }), h("div", { key: 'a5c58ec933232db9e0922da8206c2f1232b33d12', ref: el => this.minuteHand = el, class: cls('minute-hand', {
                'active': this.draggingHand === this.minuteHand,
            }), style: { transform: `translate(-50%, -100%) rotate(${this.minuteHandAngle}deg)` } }, h("span", { key: 'cee3d92e7ca639bf62bb8e07be89c9c0bc9e08e4' })), h("div", { key: '4a4adaa7889a7b102125b3edd41c6bdc82199848', ref: el => this.hourHand = el, class: cls('hour-hand', {
                'active': this.draggingHand === this.hourHand,
            }), style: { transform: `translate(-50%, -100%) rotate(${this.hourHandAngle}deg)` } }, h("span", { key: '1014250a37993139abdf421ffe7fee076ee895b0' })))));
    }
    static get is() { return "x-timepicker"; }
    static get formAssociated() { return true; }
    static get originalStyleUrls() {
        return {
            "$": ["./style.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["style.css"]
        };
    }
    static get properties() {
        return {
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input label text"
                },
                "attribute": "label",
                "reflect": false
            },
            "name": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input name for forms keys"
                },
                "attribute": "name",
                "reflect": false
            },
            "info": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input information block"
                },
                "attribute": "info",
                "reflect": false
            },
            "loading": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element show loading and block for edit"
                },
                "attribute": "loading",
                "reflect": false
            },
            "cleanable": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element input clear button"
                },
                "attribute": "cleanable",
                "reflect": false
            },
            "required": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element input required for forms validations"
                },
                "attribute": "required",
                "reflect": false
            },
            "now": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element on empty value set now time"
                },
                "attribute": "now",
                "reflect": false
            },
            "width": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input width"
                },
                "attribute": "width",
                "reflect": false
            },
            "value": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string | null",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input value"
                },
                "attribute": "value",
                "reflect": false,
                "defaultValue": "''"
            }
        };
    }
    static get states() {
        return {
            "isValid": {},
            "isFocused": {},
            "isLoading": {},
            "isDisabled": {},
            "isVisible": {},
            "hourHandAngle": {},
            "minuteHandAngle": {},
            "draggingHand": {},
            "timeSelected": {}
        };
    }
    static get events() {
        return [{
                "method": "onValidateInputEvent",
                "name": "validated",
                "bubbles": false,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "On validate input event"
                },
                "complexType": {
                    "original": "ElementInternals",
                    "resolved": "ElementInternals",
                    "references": {
                        "ElementInternals": {
                            "location": "global",
                            "id": "global::ElementInternals"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "value",
                "methodName": "watchValue"
            }];
    }
    static get attachInternalsMemberName() { return "internals"; }
}
