var _a, _b;
import { __awaiter, __decorate, __extends, __generator } from "tslib";
import Component from 'vue-class-component';
import { Model, Prop, Watch } from 'vue-property-decorator';
import { MPopupDirective } from '../../directives/popup/popup';
import { InputLabel } from '../../mixins/input-label/input-label';
import { InputState } from '../../mixins/input-state/input-state';
import { InputMaxWidth, InputWidth } from '../../mixins/input-width/input-width';
import { MediaQueries } from '../../mixins/media-queries/media-queries';
import { FormatMode } from '../../utils/i18n/i18n';
import { KeyCode } from '../../utils/keycode/keycode';
import MediaQueriesPlugin from '../../utils/media-queries/media-queries';
import uuid from '../../utils/uuid/uuid';
import { ModulVue } from '../../utils/vue/vue';
import { MButton } from '../button/button';
import { MCalendarButton } from '../calendar/calendar-button/calendar-button';
import { BUTTON_NAME, I18N_NAME, ICON_BUTTON_NAME, INPUT_STYLE_NAME, LINK_NAME, POPPER_NAME, TIMEPICKER_NAME, VALIDATION_MESSAGE_NAME } from '../component-names';
import { MI18n } from '../i18n/i18n';
import { MIconButton } from '../icon-button/icon-button';
import { MInputMask } from '../input-mask/input-mask';
import { MInputStyle } from '../input-style/input-style';
import { MLink } from '../link/link';
import { MPopup } from '../popup/popup';
import { MValidationMessage } from '../validation-message/validation-message';
import { POPUP_NAME as DIRECTIVE_POPUP_NAME } from './../../directives/directive-names';
import { InputManagement } from './../../mixins/input-management/input-management';
import WithRender from './timepicker.html?style=./timepicker.scss';
var MAXIMUM_HOURS = 23;
var MAXIMUM_MINUTES = 59;
var MINUTE_SECONDS = 60;
function validateTimeString(value) {
    var regex = /(\d\d):(\d\d)/g;
    return !(value || '').length || value.match(regex) ? true : false;
}
var MTimepicker = /** @class */ (function (_super) {
    __extends(MTimepicker, _super);
    function MTimepicker() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.i18nButton = _this.$i18n.translate('m-timepicker:button-ok');
        _this.i18nPlaceHolder = _this.$i18n.translate('m-timepicker:placeholder');
        _this.i18nOutOfBoundsError = _this.$i18n.translate('m-timepicker:out-of-bounds-error', { min: _this.min, max: _this.max }, undefined, undefined, undefined, FormatMode.Sprintf);
        _this.hours = [];
        _this.minutes = [];
        _this.internalTime = '';
        _this.internalHour = NaN;
        _this.internalMinute = NaN;
        _this.internalFilteredMinutes = [];
        _this.internalFilteredHours = [];
        _this.isMousedown = false;
        _this.internalOpen = false;
        _this.internalTimeErrorMessage = '';
        _this.id = "mTimepicker-" + uuid.generate();
        return _this;
    }
    MTimepicker.prototype.created = function () {
        this.internalTime = this.value;
        this.updatePopupTime(this.internalTime);
    };
    MTimepicker.prototype.mounted = function () {
        // create hours
        for (var i = -1; i < MAXIMUM_HOURS; i++) {
            this.hours.push(i + 1);
        }
        // create minutes
        for (var i = -1; i < MAXIMUM_MINUTES; i++) {
            this.minutes.push(i + 1);
        }
        this.internalFilteredMinutes = this.minutes;
    };
    MTimepicker.prototype.timeStringToNumber = function (value) {
        var timeString = value.split(':');
        var timeObject = {
            hour: parseInt(timeString[0], 10),
            minute: parseInt(timeString[1], 10)
        };
        return timeObject;
    };
    MTimepicker.prototype.validateTime = function (value) {
        this.internalTimeErrorMessage = '';
        if (!this.skipInputValidation && validateTimeString(value)) {
            if (this.validateTimeRange(value)) {
                this.internalTimeErrorMessage = '';
                return true;
            }
            else {
                this.internalTimeErrorMessage = this.i18nOutOfBoundsError;
                return false;
            }
        }
        return true;
    };
    MTimepicker.prototype.validateTimeRange = function (value) {
        return !value.length || (this.validateHour(value) && this.validateMinute(value));
    };
    MTimepicker.prototype.validateHour = function (value) {
        return this.timeStringToNumber(value).hour >= this.timeStringToNumber(this.min).hour &&
            this.timeStringToNumber(value).hour <= this.timeStringToNumber(this.max).hour;
    };
    MTimepicker.prototype.validateMinute = function (value) {
        if (this.timeStringToNumber(value).hour === this.timeStringToNumber(this.min).hour) {
            return this.timeStringToNumber(value).minute >= this.timeStringToNumber(this.min).minute;
        }
        else if (this.timeStringToNumber(value).hour === this.timeStringToNumber(this.max).hour) {
            return this.timeStringToNumber(value).minute <= this.timeStringToNumber(this.max).minute;
        }
        else {
            return true;
        }
    };
    MTimepicker.prototype.formatTimeString = function () {
        return this.formatNumber(this.internalHour) + ':' + this.formatNumber(this.internalMinute);
    };
    MTimepicker.prototype.formatNumber = function (value) {
        return value < 10 ? '0' + value : value.toString();
    };
    MTimepicker.prototype.scrollToSelection = function (container) {
        var selectedElement = container.querySelector('.m--is-selected');
        setTimeout(function () {
            if (selectedElement) {
                container.scrollTop = selectedElement['offsetTop'] - container.clientHeight / 2 + selectedElement.clientHeight / 2;
            }
        }, 10);
    };
    MTimepicker.prototype.positionScroll = function (el) {
        el.scrollTop = Math.round(el.scrollTop / 44) * 44;
    };
    ///////////////////////////////////////
    MTimepicker.prototype.updateInternalTime = function (value) {
        if (!this.as().isFocus || value) {
            this.currentTime = value;
        }
    };
    MTimepicker.prototype.updatePopupTime = function (value) {
        if (value) {
            this.internalHour = this.timeStringToNumber(value).hour;
            this.internalMinute = this.timeStringToNumber(value).minute;
        }
        else {
            this.resetPopupTime();
        }
    };
    MTimepicker.prototype.resetPopupTime = function () {
        this.internalHour = NaN;
        this.internalMinute = NaN;
    };
    ///////////////////////////////////////
    MTimepicker.prototype.onScroll = function (event) {
        var _this = this;
        if (!this.isMousedown) {
            clearTimeout(this.scrollTimeout);
            this.scrollTimeout = setTimeout(function () {
                // tslint:disable-next-line: deprecation
                if (event.srcElement) {
                    // tslint:disable-next-line: deprecation
                    _this.positionScroll(event.srcElement);
                }
            }, 300);
        }
    };
    MTimepicker.prototype.onSelectHour = function (hour) {
        var _this = this;
        this.internalHour = hour;
        // change available minutes in function of min/max value
        if (hour === this.timeStringToNumber(this.min).hour) {
            this.internalFilteredMinutes = this.minutes.filter(function (x) { return (x >= _this.timeStringToNumber(_this.min).minute); });
        }
        else if (hour === this.timeStringToNumber(this.max).hour) {
            this.internalFilteredMinutes = this.minutes.filter(function (x) { return (x <= _this.timeStringToNumber(_this.max).minute); });
        }
        else {
            this.internalFilteredMinutes = this.minutes;
        }
    };
    MTimepicker.prototype.onSelectHourKeyup = function ($event, hour) {
        // tslint:disable-next-line: deprecation
        if ($event.keyCode === KeyCode.M_ENTER || $event.keyCode === KeyCode.M_RETURN) {
            this.onSelectHour(hour);
        }
    };
    MTimepicker.prototype.onSelectMinute = function (minute) {
        this.internalMinute = minute;
        if (!isNaN(this.internalHour)) {
            this.currentTime = this.formatTimeString();
            this.open = false;
        }
    };
    MTimepicker.prototype.onSelectMinuteKeyup = function ($event, minute) {
        // tslint:disable-next-line: deprecation
        if ($event.keyCode === KeyCode.M_ENTER || $event.keyCode === KeyCode.M_RETURN) {
            this.onSelectMinute(minute);
        }
    };
    MTimepicker.prototype.onMousedown = function (event) {
        this.isMousedown = true;
    };
    MTimepicker.prototype.onMouseup = function (event) {
        this.isMousedown = false;
        // tslint:disable-next-line: deprecation
        if (event.srcElement) {
            // tslint:disable-next-line: deprecation
            this.positionScroll(event.srcElement);
        }
    };
    MTimepicker.prototype.onOk = function () {
        if (!isNaN(this.internalHour) && !isNaN(this.internalMinute)) {
            this.currentTime = this.formatTimeString();
        }
        this.open = false;
    };
    MTimepicker.prototype.onClose = function () {
        if (isNaN(this.internalHour) || isNaN(this.internalMinute)) {
            this.resetPopupTime();
        }
        else {
            this.updatePopupTime(this.internalTime);
        }
    };
    MTimepicker.prototype.onPopupOpen = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                this.open = true;
                this.focusInput();
                return [2 /*return*/];
            });
        });
    };
    MTimepicker.prototype.focusInput = function () {
        return __awaiter(this, void 0, void 0, function () {
            var inputEl;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.$nextTick()];
                    case 1:
                        _a.sent();
                        inputEl = this.$refs.input.$el;
                        inputEl.focus();
                        this.open = true;
                        return [2 /*return*/];
                }
            });
        });
    };
    Object.defineProperty(MTimepicker.prototype, "currentTime", {
        ///////////////////////////////////////
        get: function () {
            if (!this.internalTime) {
                return '';
            }
            var hourParts = this.internalTime.split(':');
            return hourParts.length > 1 ? hourParts[0] + ":" + hourParts[1] : '';
        },
        set: function (value) {
            var hourParts = (value || '').split(':');
            var newValue = hourParts.length > 1 ? hourParts[0] + ":" + hourParts[1] : '';
            var oldTime = this.internalTime;
            this.internalTime = newValue;
            // When the user type in something we close de popup.
            this.open = false;
            if (value && this.skipInputValidation) {
                this.$emit('input', newValue);
            }
            else if (value && this.validateTime(value) && validateTimeString(value)) {
                this.updatePopupTime(newValue);
                if (newValue !== oldTime) {
                    this.$emit('input', newValue);
                }
            }
            else {
                this.resetPopupTime();
                this.$emit('input', undefined);
            }
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "currentHour", {
        get: function () {
            return this.internalHour;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "currentMinute", {
        get: function () {
            return this.internalMinute;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "currentfilteredHours", {
        get: function () {
            var _this = this;
            return this.internalFilteredHours = this.hours.filter(function (x) { return (x >= _this.timeStringToNumber(_this.min).hour) && (x <= _this.timeStringToNumber(_this.max).hour); });
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "currentFilteredMinutes", {
        get: function () {
            var _this = this;
            return this.internalFilteredMinutes.filter(function (x) { return (x % _this.step === 0); });
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "currentStep", {
        get: function () {
            return this.step * MINUTE_SECONDS;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "timeError", {
        get: function () {
            return this.internalTimeErrorMessage !== '' || this.as().hasError;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "timeErrorMessage", {
        get: function () {
            if (this.hideInternalErrorMessage) {
                return '';
            }
            else {
                return this.internalTimeErrorMessage || this.as().errorMessage;
            }
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "open", {
        get: function () {
            return this.internalOpen;
        },
        set: function (open) {
            var _this = this;
            this.internalOpen = open;
            setTimeout(function () {
                if (_this.internalOpen) {
                    _this.scrollToSelection(_this.$refs.hours);
                    _this.scrollToSelection(_this.$refs.minutes);
                    _this.$emit('open');
                }
                else {
                    _this.$emit('close');
                }
            });
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "inputMaskOptions", {
        get: function () {
            return {
                time: true,
                timePattern: ['h', 'm']
            };
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(MTimepicker.prototype, "ariaControls", {
        get: function () {
            return this.id + '-controls';
        },
        enumerable: true,
        configurable: true
    });
    __decorate([
        Model('input')
    ], MTimepicker.prototype, "value", void 0);
    __decorate([
        Prop({ default: '00:00' })
    ], MTimepicker.prototype, "min", void 0);
    __decorate([
        Prop({ default: '23:59' })
    ], MTimepicker.prototype, "max", void 0);
    __decorate([
        Prop({ default: 5 })
    ], MTimepicker.prototype, "step", void 0);
    __decorate([
        Prop({ default: InputMaxWidth.Small })
    ], MTimepicker.prototype, "maxWidth", void 0);
    __decorate([
        Prop({ default: false })
    ], MTimepicker.prototype, "hideInternalErrorMessage", void 0);
    __decorate([
        Prop({ default: false })
    ], MTimepicker.prototype, "skipInputValidation", void 0);
    __decorate([
        Watch('value')
    ], MTimepicker.prototype, "updateInternalTime", null);
    MTimepicker = __decorate([
        WithRender,
        Component({
            components: (_a = {},
                _a[BUTTON_NAME] = MButton,
                _a[POPPER_NAME] = MPopup,
                _a[ICON_BUTTON_NAME] = MIconButton,
                _a[VALIDATION_MESSAGE_NAME] = MValidationMessage,
                _a[LINK_NAME] = MLink,
                _a[INPUT_STYLE_NAME] = MInputStyle,
                _a[I18N_NAME] = MI18n,
                _a.MInputMask = MInputMask,
                _a.MCalendarButton = MCalendarButton,
                _a),
            directives: (_b = {},
                _b[DIRECTIVE_POPUP_NAME] = MPopupDirective,
                _b),
            mixins: [
                InputState,
                InputManagement,
                InputWidth,
                MediaQueries,
                InputLabel
            ]
        })
    ], MTimepicker);
    return MTimepicker;
}(ModulVue));
export { MTimepicker };
var TimepickerPlugin = {
    install: function (v) {
        v.use(MediaQueriesPlugin);
        v.component(TIMEPICKER_NAME, MTimepicker);
    }
};
export default TimepickerPlugin;
//# sourceMappingURL=timepicker.js.map