//TODO: extend library to except localization

function initializeNumberInputs() {
    var inputs = $('input.numberInput');
    if (inputs.length < 1) return;

    var val;
    $.each(inputs, function (index, value) {
        val = $(value).val();
        if (val !== "") {
            $(value).val(formatValue(value, val));
        }
    });
}

function formatNumberInput($element) {
    if ($element.val() === "")
        return;

    $element.val(formatValue($element, $element.val()));
}

function roundToPercision(percision, num) {
    return num.toFixed(percision);
}

function formatAndRoundToPercision(percision, num) {
    return roundToPercision(percision, num).replace(".", ",");
}

function formatElementText(num) {
    return formatValue(null, num);
}

function formatValue(element, value) {
    if (!value || value === '-')
        return;

    value = toNumber(value);

    if ($(element).attr('data-round')) {
        return roundAndFormatValue(element, value);
    } else {
        var step = $(element).attr('step');
        if (!step)
            step = 2;
        else
            step = toNumber(step);

        var evenRoundedValue = evenRound(value, step);
        return formatDisplay(step, evenRoundedValue);
    }
}

function roundAndFormatValue(element, value) {
    var decimals = $(element).attr('data-round');
    let roundedValue = evenRound(value, decimals);

    var step = $(element).attr('step');
    if (!step)
        step = 2;
    else
        step = toNumber(step);

    return formatDisplay(step, roundedValue);
}

function formatDisplay(decimalPlaces, value, removeDecimalPoint) {
    if (value === null || value === undefined)
        value = 0;

    if (decimalPlaces === null || decimalPlaces === undefined)
        decimalPlaces = countDecimals(value);

    value = toNumber(value);

    var roundedValue = round(value, decimalPlaces);
    roundedValue = isNaN(roundedValue) ? value : roundedValue;

    var stringValue = roundedValue.toLocaleString('sl-SI', { minimumFractionDigits: decimalPlaces, maximumFractionDigits: decimalPlaces });

    if (removeDecimalPoint && stringValue.indexOf(".") > 0)
        stringValue = stringValue.replace(/\./g, "");

    var decimalPieces = stringValue.split(',');
    var currentDecimalPlaces = decimalPieces.length > 1 ? decimalPieces[1].length : 0;

    if (decimalPieces.length < 2 && decimalPlaces > 0)
        stringValue += ",";

    for (var i = currentDecimalPlaces; i < decimalPlaces; i++) {
        stringValue += "0";
    }

    return stringValue.replace("−", "-");
}

function toNumber(value) {
    let calcValue = (value + "").replace("−", "-");
    if (calcValue && calcValue.indexOf(",") > 0 && calcValue.indexOf(".") > 0)
        calcValue = calcValue.replace(/\./g, '');

    var number = parseFloat(calcValue.replace(/,/g, '.'));
    return isNaN(number) ? 0 : number;
}

function evenRound(num, decimalPlaces) {
    var d = decimalPlaces || 0;
    var m = Math.pow(10, d);
    var n = +(d ? num * m : num).toFixed(8);
    var i = Math.floor(n), f = n - i;
    var e = 1e-8;
    var r = (f > 0.5 - e && f < 0.5 + e) ?
        ((i % 2 === 0) ? i : i + 1) : Math.round(n);
    return d ? r / m : r;
}

function resetValue(element, previousValue) {
    element.val(previousValue);
}

function round(value, decimals) {
    if (!decimals) decimals = 2;
    let percision = Math.floor(parseFloat(value)).toString().length + parseFloat(decimals) + 1;

    return Number(Math.round(parseFloat(value).toPrecision(percision) + 'e' + decimals) + 'e-' + decimals);
}

function countDecimals(number) {
    if (Math.floor(number.valueOf()) === number.valueOf()) return 0;

    var str = number.toString().replace(/,/g, '.');
    if (str.indexOf(".") !== -1 && str.indexOf("-") !== -1) {
        return str.split("-")[1] || 0;
    } else if (str.indexOf(".") !== -1) {
        return str.split(".")[1].length || 0;
    }

    return str.split("-")[1] || 0;
}

$(document).ready(function () {
    initializeNumberInputs();

    var lastInput = "";
    $("body").on('keydown', 'input.numberInput', function () {
        var val = $(this).val().replace(/,/g, '.');
        if (!isNaN(val)) {
            lastInput = formatValue($(this), val);
        }
    });

    $("body").on('keyup', 'input.numberInput', function (e) {
        let code = e.which;
        if (code === 9 || code === 32 || code === 13 || code === 188 || code === 186) //Skip if TAB or Enter
            return;

        var val = $(this).val().replace(/,/g, '.');

        if (isNaN(val) && val !== '-') {
            resetValue($(this), lastInput);
            return;
        }

        var step = $(this).attr('step');
        if (step && step !== 'any') {
            var splittedValueParts = val.split('.');

            if (e.key === ',' && step === 0) {
                resetValue($(this), lastInput);
                return;
            }

            if (splittedValueParts.length > 1 && splittedValueParts[1].length > step) {
                resetValue($(this), lastInput);
                return;
            }
        }
    });

    $("body").on('blur', 'input.numberInput', function () {
        lastInput = "";
        if (($(this).val() === '' || $(this).val() === '-') && $(this).hasClass("required")) {
            $(this).val('0,00');
        }
    });

    $("body").on('change', 'input.numberInput', function () {
        $(this).val(formatValue($(this), $(this).val()));

        var inputMin = Number($(this).attr("data-min"));
        var inputMax = Number($(this).attr("data-max"));
        var number = Number(toNumber($(this).val()));

        if (inputMin > number || inputMax < number) {
            $(this)[0].setCustomValidity($('#RabateValidationError').attr('data-text'));
        } else {
            $(this)[0].setCustomValidity('');
        }

        if (!$(this)[0].checkValidity()) {
            $(this).addClass('error-input-item');
            $(this).trigger("numberinput-error");
        } else {
            $(this).removeClass('error-input-item');
        }
    });

    $("body").on('submit', 'form', function (e) {
        $(this).find(".numberInputClone").each(function () {
            $(this).prev(".numberInput").attr("name", $(this).attr("name"));
        });

        $(this).find(".numberInput").each(function () {
            let $clone = $(this).clone();
            $clone.val(formatDisplay($clone.attr("step"), $clone.val(), true)).removeAttr("id").addClass("numberInputClone").hide();
            $(this).removeAttr("name");
            $(this).after($clone);
        });
    });
});