document.addEventListener('DOMContentLoaded', () => {
    $(document).ready(function(){
        /**
         * 
         * @param {*} fields 
         * @param {*} validations 
         * @returns 
         */
         $.fn.runValidations = function(fields,validations,options={"showErrorsAferRun":true}){
            let errors = [];
            let callbacks = [];
            for(let field in fields){
                for(let validation of validations){
                    let isValid = validation.run({
                        "key":field,
                        "value":fields[field]
                    });
                    if(!isValid){
                        errors.push({
                            name:validation.name,
                            message:validation.message,
                            field:field,
                            haveCallback:(validation.errorCallback !== undefined)
                        });
                        if(validation.errorCallback !== undefined)
                            callbacks.push(validation.errorCallback);                        
                    }
                        
                }
            }
            if(options.showErrorsAferRun){
                $.fn.showErrors(errors);
                $.fn.runCallbackErrors(callbacks);
            }
            return {
                valid:(errors.length === 0),
                errors:errors
            };
        }
    
        /**
         * 
         * @param {*} element 
         * @param {*} inputs 
         * @returns 
         */
         $.fn.getInputsFromForm = function (element, nodeName="INPUT", type="text", inputs = []){
            try {
                for(let child of element.childNodes){
                    if((child.nodeName === nodeName) && ((child.type === type) || (nodeName ==="TEXTAREA"))){
                        inputs.push(child)
                    }else
                        $.fn.getInputsFromForm.call(this,child,nodeName,type,inputs)
                }
                return inputs;
            } catch (error) {
                throw error;
            }
        }
    
        /**
         * 
         * @param {*} element 
         * @param {*} inputs 
         * @returns 
         */
        $.fn.getSelectFromForm = function (element, nodeName, selects = []){
            try {
                for(let child of element.childNodes){
                    if(child.nodeName === nodeName)
                        selects.push(child);
                    else
                        $.fn.getSelectFromForm.call(this,child,nodeName,selects);
                }
                return selects;
            } catch (error) {
                throw error;
            }
        }
    
        /**
         * 
         * @param {*} form 
         */
        $.fn.getDataForm = function(form){
            let data = {};
            let inputTexts = $.fn.getInputsFromForm.call(this,form);
            let inputRadios = $.fn.getInputsFromForm.call(this,form,"INPUT","radio");
            let inputPassword = $.fn.getInputsFromForm.call(this,form,"INPUT","password");
            let textareas   = $.fn.getInputsFromForm.call(this,form,"TEXTAREA");
            let inputsHidden   = $.fn.getInputsFromForm.call(this,form,"INPUT","hidden");
            let selects     = $.fn.getSelectFromForm.call(this,form,"SELECT");
            
            Object.assign(data,
                $.fn.normalizeInputsText.call(this,inputTexts),
                $.fn.normalizeInputsText.call(this,inputPassword),
                $.fn.normalizeInputsRadio.call(this,inputRadios),
                $.fn.normalizeInputsText.call(this,textareas),
                $.fn.normalizeInputsText.call(this,inputsHidden),
                $.fn.normalizeInputsSelect.call(this,selects),
            );        
    
            if (data.hasOwnProperty('')) {
                delete data[''];
              }
    
            return data;
        }
    
        /**
         * 
         * @param {*} inputTexts 
         * @returns 
         */
        $.fn.normalizeInputsSelect = function(selects){
            let data = {};
            if(selects.length > 0){
                selects.map((field) => {
                    data[field.name]=$("#"+field.id).val();
                });
            }
            return data;
        }
    
        /**
         * 
         * @param {*} inputTexts 
         * @returns 
         */
        $.fn.normalizeInputsText = function(inputTexts){
            let data = {};
            if(inputTexts.length > 0){
                inputTexts.map((field) => {
                    data[field.name]=field.value;
                });
            }
            return data;
        }
    
        /**
         * 
         * @param {*} inputRadios 
         */
        $.fn.normalizeInputsRadio = function (inputRadios){
            try {
                let data = {};
                if(inputRadios.length > 0){
                    let input = inputRadios.find((inp)=>inp.checked);
                    if(!input){
                        data[inputRadios[0].name] = null;
                        return data;
                    }
                    data[input.name] = input.value;
                }
                return data;
            } catch (error) {
                console.log(error);
            }
        }
    
        $.fn.runCallbackErrors = function(errors){
            errors.forEach((c)=>c());
        }
    
        /**
         * 
         * @param {*} errors 
         */
        $.fn.showErrors = function(errors){
            errors.forEach((err,index)=>{
                if(!err.haveCallback){
                    let div = $("<div id='div-"+err.field+"'></div>");
                    let label = $("<label></label>");
                    label.css("color","red").css("font-size","13px");
                    label.text(err.message);
                    div.append(label);
                    $("#div-"+err.field).remove();
                    $('[name="'+err.field+'"]').parent().append(div);
    
                    $('[name="'+err.field+'"]').css(
                        "border-color",
                        "red"
                    )
                    $('[name="'+err.field+'"]').on("focus",function(){
                        $('[name="'+err.field+'"]').css(
                            "border-color",
                            "#ced4da"
                        );
                        div.remove();
                    });
                }
            })
        }
    });
})
