/**
 * (c) by aheadware.com
 */

var app = app || {};
app.util = app.util || {};

/**
 * Form utilitiies
 *
 * Usage:
 *
 * .html
 *
 * <input data-validate
 *        data-validate-required
 *        [data-validate-email|data-validate-regex=""|data-validate-custom="{FunctionName}"]
 *        data-validate-msg="Error message" />
 *
 * Regex example for password requires min 4 chars and max 32
 * data-validate-regex="/^([a-zA-Z0-9_-]){4,32}$/"
 *
 * @type {{disableAutoSubmit: app.util.Form.disableAutoSubmit, getFormData: (function(*)), getInvalidInputs: (function(*, *=): Array), getValidationInputs: (function(*): (number | * | BigInt | T)), isValidInput: app.util.Form.isValidInput, markInputAsValid: app.util.Form.markInputAsValid, markInputAsInvalid: app.util.Form.markInputAsInvalid, validateForm: (function(*=, *=): boolean)}}
 */
app.util.Form = {

    /**
     * Simple native bootstrap approach to validate form
     * @param $form
     */
    bootstrapValidate : function( $form )
    {
        let isValid = $form.get(0).checkValidity();
        $form.addClass( 'was-validated' );

        return isValid;
    }

    ,

    disableAutoSubmit : function( $form )
    {
        $form.submit( function() {
            return false;
        });
    }

    ,

    getFormData : function ( $form  )
    {
        var disabled = $form.find(':input:disabled').removeAttr('disabled'),
            arr = $form.serializeArray(),
            data = {};
        for ( var ai = 0; ai < arr.length; ai++ )
        {
            data[ arr[ ai ].name ] = arr[ ai ].value;
        }

        disabled.attr('disabled','disabled');

        return data;
    }

    ,

    getInvalidInputs : function( $form, cv )
    {
        var inputs = $form.find('[data-validate]'),
            $invalidInputs = [],
            customValidators = cv || {};

        $.each(inputs, function (i, input)
        {
            var $input = $(input),
                regex, val;

            if (false === isValidInput($input))
            {
                $invalidInputs.push($input);
            }

        });

        return $invalidInputs;
    }

    ,

    getValidationInputs : function( $form )
    {
        return $form.find( '[data-validate]' );
    }

    ,

    isValidInput : function( $input, customValidators )
    {
        var $input = $($input),
            customValidators = customValidators || {};

        // Dont process invisble items
        if (false == $input.is(':visible')) return true;

        if ('checkbox' === $input.attr('type'))
        {
            if ($input.is('[data-validate-required]'))
            {
                if (false === $input.is(':checked'))
                {
                    return false;
                }
            }
        }
        else if ('file' === $input.attr('type') && false === $input.is('[data-validate-custom'))
        {
            // If FileReader does not exists - we mark file as valid since we have no way to validate it
            if (typeof FileReader === "undefined") return true;

            if ($input.is('[data-max-filesize]'))
            {
                if ($input.get(0).files.length === 0) return true;
                return ($input.get(0).files[0].size < parseInt($input.attr('data-max-filesize')));
            }
        }
        else {

            if ($input.is('[data-validate-regex]'))
            {
                val = $input.val();
                regex = new RegExp(eval($input.attr('data-validate-regex')));
                if ( !val.match( regex ) )
                {
                    return false;
                }
            }

            else if ( $input.is('[data-validate-email]' ) )
            {
                val = $input.val();
                regex = new RegExp(eval("/^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/;"));
                if ( !val.match( ) )
                {
                    return false;
                }
            }

            else if ($input.is('[data-validate-required]'))
            {
                val = $input.val().trim();
                if (val.length === 0)
                {
                    return false;
                }
            }

            else if ($input.is('[data-validate-custom'))
            {
                if (customValidators.hasOwnProperty( $input.attr( 'data-validate-custom' ) ) &&
                    "function" === typeof customValidators[ $input.attr( 'data-validate-custom' ) ] )
                {
                    if ( false === customValidators[ $input.attr( 'data-validate-custom' ) ]( $input ) )
                    {
                        return false;
                    }
                }
            }

        }

        return true;
    }

    ,

    markInputAsValid : function( $input )
    {
        // Normal form group input field
        if ( $input.closest( 'div.form-group' ).length > 0 )
        {
            $input.closest( 'div.form-group' ).first().removeClass('has-error').addClass('has-success').addClass('has-feedback');
            if ( $input.next('span.glyphicon ').length !== 0 )
            {
                $input.next('span.glyphicon ').removeClass('glyphicon-remove').addClass('glyphicon-ok');
            }
            else
            {
                $('<span class="glyphicon glyphicon-ok form-control-feedback"></span>').insertAfter( $input );
            }
            if ($input.nextAll('small.help-block').length !== 0 )
            {
                $input.nextAll('small.help-block').remove();
            }
        }
        else if ( $input.parent( 'div').hasClass( 'input-group') )
        {
            // Input field with addon
            $input.parent('div.input-group').removeClass('has-error').addClass('has-success');
            $input.parent('div.input-group').parent('div.form-group').removeClass('has-error').addClass('has-success');
            if ( $input.parent( 'div.input-group' ).nextAll('small.help-block').length !== 0 )
            {
                $input.parent( 'div.input-group' ).nextAll('small.help-block').remove();
            }

        }
    }
    ,

    markInputAsInvalid : function( $input )
    {
        // Error
        if ( $input.attr( 'type' ) == "checkbox" )
        {
            // @todo How to show error on checkboxes
            //TB.Ext.Notification.show( $input.attr( 'data-validate-errormsg' ), TB.Ext.Notification.TYPE_DANGER );
        }
        else
        {
            // Normal form group input field
            if ( $input.closest( 'div.form-group' ).length > 0 )
            {
                $input.closest( 'div.form-group' ).first().removeClass('has-success').addClass('has-error').addClass('has-feedback');
                if ( $input.next('span.glyphicon ').length !== 0 )
                {
                    $input.next('span.glyphicon ').removeClass('glyphicon-ok').addClass('glyphicon-remove');
                }
                else
                {
                    $( '<span class="glyphicon glyphicon-remove form-control-feedback"></span>').insertAfter( $input );
                }

                if ( $input.is("[data-validate-msg]") && $input.nextAll('small.help-block').length === 0 )
                {
                    $('<small class="help-block">' + $input.attr('data-validate-msg') + '</small>').insertAfter( $input.next('span.glyphicon ') );
                }
            }
            else if ( $input.parent( 'div').hasClass( 'input-group') )
            {
                // Input Fields with addons
                $input.parent('div.input-group').removeClass('has-success').addClass('has-error');
                $input.parent('div.input-group').parent('div.form-group').removeClass('has-success').addClass('has-error');
                if ( $input.is("[data-validate-msg]") && $input.parent( 'div.input-group' ).nextAll('small.help-block').length === 0 )
                {
                    $('<small class="help-block">' + $input.attr('data-validate-msg') + '</small>').insertAfter( $input.parent( 'div.input-group' ) );
                }
            }
        }
    }

    ,

    validateForm : function( $form, customValidators )
    {
        var $inputs = this.getValidationInputs( $form ),
            isFormValid = true,
            $input;

        if ( $inputs && $inputs.length )
        {
            for ( var vi = 0; vi < $inputs.length; vi++ )
            {
                $input = $( $inputs[ vi ] );

                if ( this.isValidInput( $input, customValidators ) )
                {
                    this.markInputAsValid( $input );
                }
                else
                {
                    isFormValid = false;

                    this.markInputAsInvalid( $input );

                }
            }
        }

        return isFormValid;
    }
};