/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
import { isDate, Platform } from '@tylertech/forge-core';
import { isSameDate } from '../core';
import { BaseDatePickerCore } from './base/base-date-picker-core';
import { DATE_PICKER_CONSTANTS } from './date-picker-constants';
export class DatePickerCore extends BaseDatePickerCore {
    constructor(adapter) {
        super(adapter);
        this._mode = 'single';
    }
    _initializeState() {
        if (!this._value) {
            this._value = this._coerceDateValue(this._adapter.getInputValue());
        }
    }
    _emitChangeEvent(value, force) {
        const typedValue = this._getTypedValue(value);
        const wasCancelled = !this._adapter.emitHostEvent(DATE_PICKER_CONSTANTS.events.CHANGE, typedValue, true, !force);
        if (!wasCancelled) {
            this._setValue(value);
            return true;
        }
        return false;
    }
    _emitOpenEvent() {
        this._adapter.emitHostEvent(DATE_PICKER_CONSTANTS.events.OPEN, undefined, false);
    }
    _emitCloseEvent() {
        this._adapter.emitHostEvent(DATE_PICKER_CONSTANTS.events.CLOSE, undefined, false);
    }
    _onToday() {
        const today = new Date();
        today.setHours(0, 0, 0, 0);
        this._onDateSelected({ date: today, selected: true, type: 'date' });
    }
    _onClear() {
        this._onDateSelected({ date: null, selected: false, type: 'date' });
    }
    _getCurrentValue() {
        return this._value;
    }
    _setFormattedInputValue(suppressValueChanges) {
        const formattedDate = this._formatDate(this._value);
        if (formattedDate) {
            this._adapter.setInputValue(formattedDate, suppressValueChanges ? false : this._notifyInputValueChanges);
        }
        else {
            if (!this._allowInvalidDate) {
                this._adapter.setInputValue('', suppressValueChanges ? false : this._notifyInputValueChanges);
            }
        }
    }
    _setValue(value) {
        if (!value || this._isDateValueAcceptable(value)) {
            this._value = value;
        }
    }
    _onDateSelected(event) {
        const value = event.date;
        if (event.type === 'date') {
            this._closeCalendar(true);
        }
        if (!this._emitChangeEvent(value)) {
            return;
        }
        const formattedValue = this._formatDate(value);
        this._adapter.setInputValue(formattedValue, this._notifyInputValueChanges);
        this._formatInputValue();
        if (!Platform.isMobile) {
            this._adapter.selectInputText();
        }
    }
    _openCalendar(emitOpenEvent) {
        super._openCalendar(emitOpenEvent);
        const currentValue = this._getCurrentValue();
        if (!!currentValue) {
            this._adapter.goToCalendarDate(new Date(currentValue));
        }
    }
    _applyMin() {
        if (this._value && !this._isDateValueAcceptable(this._value)) {
            this._emitChangeEvent(null, true);
            this._setFormattedInputValue();
        }
        super._applyMin();
    }
    _applyMax() {
        if (this._value && !this._isDateValueAcceptable(this._value)) {
            this._emitChangeEvent(null, true);
            this._setFormattedInputValue();
        }
        super._applyMax();
    }
    _applyDisabledDates() {
        if (this._value && !this._isDateValueAcceptable(this._value)) {
            this._emitChangeEvent(null, true);
            this._setFormattedInputValue();
        }
    }
    _applyDisabledDaysOfWeek() {
        if (this._value && !this._isDateValueAcceptable(this._value)) {
            this._emitChangeEvent(null, true);
            this._setFormattedInputValue();
        }
    }
    _handleInput(value) {
        const sanitizedValue = this._getSanitizedDateString(value);
        const date = this._coerceDateValue(sanitizedValue);
        if (this._masked) {
            this._adapter.emitInputEvent(DATE_PICKER_CONSTANTS.events.INPUT, sanitizedValue);
        }
        if (!isSameDate(date, this._value) && this._isDateValueAcceptable(date)) {
            this._emitChangeEvent(date);
        }
    }
    _onInputValueChanged(value) {
        const sanitizedValue = this._getSanitizedDateString(value);
        if (this._masked && sanitizedValue) {
            // If masked, allow clearing value by setting input.value directly
            // To set a date value, dispatch `input` event and mask will handle it.
            return;
        }
        const date = this._coerceDateValue(sanitizedValue);
        if (!isSameDate(date, this._value) && this._isDateValueAcceptable(date)) {
            this.value = date;
            this._emitChangeEvent(this._value);
        }
    }
    _applyValue() {
        this._setFormattedInputValue();
        if (this._open) {
            this._adapter.setCalendarValue(this._value);
        }
    }
    get value() {
        const date = this._getTypedValue(this._value);
        if (!date) {
            return null;
        }
        if (isDate(date)) {
            return new Date(date.getTime());
        }
        return date;
    }
    set value(value) {
        if (this._value !== value) {
            this._setValue(this._coerceDateValue(value));
            if (this._isInitialized) {
                this._applyValue();
            }
        }
    }
}
