/* Check a value wheather is empty */
function isEmptyValue(val)
{
    return val === null || val === undefined || (typeof val === 'string' && !val.trim().length);
}

/* Validate method settings data */
function validateFormData($form)
{
    let hasError = false;
    $form.find('.form-tip').remove();
    $.each(methodSettings, function(name, setting)
    {
        if($form.find('.form-group[data-name="' + name + '"], .form-group[data-name="' + name + '[]"]').css('display') == 'none') return;

        const $control = $('#' + name);
        if(!$control.length) return;

        $($control).closest('.form-group').find('.form-tip').remove();
        $($control).removeClass('has-error');

        const isList = setting.type === 'list';
        let value    = $control.val();
        if(isList && $control.hasClass('check-list'))
        {
            value = $control.find('input:checked').map(function(){return this.value}).get();
        }

        const isEnum = setting.type === 'enum';
        if(isEnum && $control.hasClass('check-list'))
        {
            value = $control.find('input:checked').map(function(){return this.value}).get()[0];
        }

        if($control.hasClass('picker-box')) value = $control.zui('picker').$.value;

        let isEmpty = isList ? (!value || !value.length) : isEmptyValue(value);
        let $label = $('#' + name + 'Label');
        if(setting.required && isEmpty)
        {
            if($label.length) $label.remove();
            $label = '<div id="' + name + 'Label" class="text-danger form-tip">' + validMsg.required.replace('%s', setting.label) + '</div>';
            $control.closest('.form-group').append($label);
            $control.addClass('has-error');
            hasError = true;
            return false;
        }

        if(!isEmpty && setting.type === 'number')
        {
            if(!/^(-?\d+)(\.\d+)?$/.test(value))
            {
                if($label.length) $label.remove();
                $label = '<div id="' + name + 'Label" class="text-danger form-tip">' + validMsg.numberType.replace('%s', setting.label) + '</div>';
                $control.closest('.form-group').append($label);
                $control.addClass('has-error');
                hasError = true;
                return false;
            }

            if((!isNaN(setting.min) && parseFloat(value) <= setting.min) || (!isNaN(setting.max) && parseFloat(value) >= setting.max))
            {
                if($label.length) $label.remove();
                var error = validMsg.numberRange.replace(/%s/, setting.label);
                if(!isNaN(setting.min) && !isNaN(setting.max))
                {
                    error = error.replace(/%s/, setting.min + ' < ').replace(/%s/, ' < ' + setting.max);
                }
                else if(!isNaN(setting.min))
                {
                    error = error.replace(/%s/, '').replace(/%s/, ' ≥ ' + setting.min);
                }
                else
                {
                    error = error.replace(/%s/, '').replace(/%s/, ' ≤ ' + setting.max);
                }
                $label = '<div id="' + name + 'Label" class="text-danger form-tip">' + (setting.error || error) + '</div>';
                $control.closest('.form-group').append($label);
                $control.addClass('has-error');
                hasError = true;
                return false;
            }

            if(setting.gt)
            {
                var gtValue = $('#' + setting.gt).val();
                var s1      = setting.label;
                var s2      = methodSettings[setting.gt].label;
                if(parseInt(value) < parseInt(gtValue))
                {
                    if($label.length) $label.remove();
                    $label = '<div id="' + name + 'Label" class="text-danger form-tip">' + validMsg.gtError.replace('%s1', s1).replace('%s2', s2) + '</div>';
                    $control.closest('.form-group').append($label);
                    $control.addClass('has-error');
                    hasError = true;
                    return false;
                }
            }
        }

        if(!isEmpty && setting.type == 'list' && setting.listType == 'number')
        {
            var values = value.split(',');
            for(var i = 0; i < values.length; i++)
            {
                var numStr = values[i].trim();
                if(!/^(-?\d+)(\.\d+)?$/.test(numStr))
                {
                    if($label.length) $label.remove();
                    $label = '<div id="' + name + 'Label" class="text-danger form-tip">' + setting.error || validMsg.numberType.replace('%s', setting.label) + '</div>';
                    $control.closest('.form-group').append($label);
                    $control.addClass('has-error');
                    hasError = true;
                    return false;
                }

                if(setting.pattern && !new RegExp(eval(setting.pattern)).test(numStr))
                {
                    if($label.length) $label.remove();
                    $label = '<div id="' + name + 'Label" class="text-danger form-tip">' + setting.error || validMsg.numberType.replace('%s', setting.label) + '</div>';
                    $control.closest('.form-group').append($label);
                    $control.addClass('has-error');
                    hasError = true;
                    return false;
                }
            }
        }
        else if(!isEmpty)
        {
            if(setting.pattern && !new RegExp(eval(setting.pattern)).test(value))
            {
                if($label.length) $label.remove();
                $label = '<div id="' + name + 'Label" class="text-danger form-tip">' + setting.error || validMsg.numberType.replace('%s', setting.label) + '</div>';
                $control.closest('.form-group').append($label);
                $control.addClass('has-error');
                hasError = true;
                return false;
            }
        }
    });
    if(hasError) return false;
}

/** Check method settings condition */
window.checkSettingsConditions = function(form)
{
    if(!methodSettings) return;

    const $form    = $(form);
    const formData = {};

    const serializeForm = serializeArrayCustom($(form).find('form')[0]);
    serializeForm.forEach(function(item)
    {
        var oldValue = formData[item.name];
        if(Array.isArray(oldValue))     oldValue.push(item.value);
        else if(oldValue !== undefined) formData[item.name] = [oldValue, item.value];
        else formData[item.name] = item.value;
    });

    $.each(methodSettings, function(name, setting)
    {
        let conditions = setting.conditions;
        if(!conditions) return;
        if(!Array.isArray(conditions)) conditions = [conditions];
        let isMatch = false;
        for(var i = 0; i < conditions.length; ++i)
        {
            const condition    = conditions[i];
            let conditionMatch = true;
            $.each(condition, function(name, value)
            {
                const currentValue = formData[name];
                if(currentValue !== value && JSON.stringify(currentValue) !== JSON.stringify(value))
                {
                    conditionMatch = false;
                    return false;
                }
            });
            if(conditionMatch)
            {
                isMatch = true;
                break;
            }
        }
        $form.find(`.form-group[data-name="${name}"],.form-group[data-name="${name}[]"]`).css({ display: isMatch ? 'block' : 'none' });
    });
}

function serializeArrayCustom(form)
{
    const data = [];
    const elements = form.elements;

    for(let i = 0; i < elements.length; i++)
    {
        const element = elements[i];
        const $parent = $(element).closest('.form-control');

        if(element.name && !element.disabled && (element.type !== 'file' && element.type !== 'reset' && element.type !== 'submit' && element.type !== 'button'))
        {
            if($parent?.length && $parent.hasClass('picker-select'))
            {
                const $picker = $parent.closest('.picker-box');
                data.push({name: element.name, value: $picker.zui('picker').$.value});
            }
            else if(element.type === 'checkbox' || element.type === 'radio')
            {
                if(element.checked) data.push({name: element.name, value: element.value});
            }
            else
            {
                data.push({name: element.name, value: element.value});
            }
        }
    }
    return data;
}

window.submitForm = function(e)
{
    const form = $(e).closest('form');
    const url  = form.attr('action');
    const data = new FormData(form[0]);

    if(validateFormData($('.form')) == false) return;
    $.ajaxSubmit({url, data});
}
