
class AbstractSmartDateNumericPart extends AbstractSmartDatePart
{
    constructor(placeholder, size)
    {
        super(placeholder, false);
        this._numericValue = 0;
        this._size = size;
    }
    
    numericValue()
    {
        return this._numericValue;
    }
    
    /**
     * @param {Date} date
     * @returns {String}
     */
    formatDate(date)
    {
        return '';
    }
    
    formatValue(value)
    {
        let stringValue = String(this._correctValue(value));
        
        if (stringValue === '0') {
            return stringValue;
        }
        
        if (stringValue.length > this._size) {
            return stringValue.substring(0, this._size);
        }
        
        if (stringValue.length < this._size) {
            return stringValue.padStart(this._size, '0');
        }
        
        return stringValue;
    }
    
    _correctValue(value)
    {
        return Math.round(value);
    }
    
    /**
     * @param {SmartDateCheckState} state
     * @returns {String}
     */
    scanStringNumber(state)
    {
        let index = state.valueIndex();
        let value = state.value();
        
        while (index < value.length && this._isNumericSymbol(value[index])) {
            index++;
        }
        
        let stringValue = value.substring(state.valueIndex(), index);
        
        state.setValueIndex(index);
        
        return stringValue;
    }
    
    calculateNumericValue(stringValue, maximalNumber)
    {
        var startIndex = 0;
        var endIndex = 0;
        var numericValue = 0;
        
        while (startIndex < stringValue.length && stringValue[startIndex] === 0) {
            startIndex++;
        }
        
        endIndex = startIndex;
        
        while (endIndex < stringValue.length && numericValue < maximalNumber) {
            numericValue = numericValue * 10 + Number(stringValue[endIndex]);
            endIndex++;
        }
        
        if (numericValue > maximalNumber) {
            endIndex--;
        }
        
        return Number(stringValue.substring(startIndex, endIndex));
    }
    
    /**
     * @param {SmartDateCheckState} state
     * @param {Number} maximalValue
     */
    scanValue(state, maximalValue)
    {
        let index = state.valueIndex();
        let value = state.value();
        
        let numericValue = 0;
        
        while (index < value.length && this._isNumericSymbol(value[index]) && numericValue < maximalValue) {
            numericValue = numericValue * 10 + Number(value[index]);
            index++;
        }
        
        if (numericValue > maximalValue) {
            index--;
        }
        
        let stringValue = value.substring(state.valueIndex(), index);
        
        state.setValueIndex(index);
        
        return stringValue;
    }
    
    _defineParsingState(maximalValue, isAtEnd)
    {
        if (this._numericValue > 0 && (this._parsedValue.length >= this._size || !isAtEnd)) {
            this._state = AbstractSmartDatePart.STATE_COMPLETE;
            return;
        }

        if (this._numericValue * 10 > maximalValue) {
            this._state = AbstractSmartDatePart.STATE_COMPLETE;
            return;
        }
        
        this._state = AbstractSmartDatePart.STATE_INCOMPLETE;
    }
    
    _defineCleanValue()
    {
        this._cleanedValue = '';
        
        if (this.isNoState()) {
            return;
        }
        
        if (this.isComplete()) {
            this._cleanedValue = this.formatValue(this._numericValue);
            return;
        }
        
        if (this._parsedValue.length > 0) {
            this._cleanedValue = String(this._numericValue);
        }
    }
}
