(function($,undefined){
    window.forms = [];
    var regex = {
        phone: /^[\+]?[0-9 \/\-]{6,20}$/,
        email: /^[a-z0-9!#$%&'*+\/=?\^_`\{|\}~\-öäü]+(?:\.[a-z0-9!#$%&'\*\+\/=\?\^_`\{|\}~\-öäü]+)*@(?:[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?\.)+[a-z](?:[a-z\-]*[a-z])?$/i,
        date: /^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/,
        image: /^((\\|\/)?[a-zA-Z0-9\s_@\-^!#$%&+={}\[\]\.]+)+\.[0-9a-zA-Z]+$/i,
        url: /^(https?:\/\/)?((([äöüa-z\d]([äüöa-z\d-]*[äöüa-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3}))(\:\d+)?(\/[-a-zäöü\d%_.~+]*)*(\?[\[\];&a-z\d%_.~+=-]*)?(\#[-a-z\d_]*)?$/i,
        currency: /^\d{1,3}(\.\d{3})*,\d{2}$/,
        number: /^(\d+|\d{1,3}(\.\d{3})*)(,\d+)?$/,
        zip: /^\d{5}$/,
        digit: /\d/,
        name: /^[a-zA-ZäöüÄÖÜß\- ]+$/,
        licenseplate: /^[a-zA-Z]{1,3}[\-\s]?[a-zA-Z]{1,2}[\-\s]?\d{1,4}/,
        housenumber: /^\d+[a-zA-Z]?$/
    };

    var decimalPlaces = /,(\d+)$/,
        everythingButNumbers = /[^\d]+/g,
        onlyNumbers = /^\d+$/;

    function parseNumber(str){
        var val = decimalPlaces.exec(str),
            number = (str.replace(decimalPlaces, '')).replace(everythingButNumbers, '');
        if(val){
            number +='.'+val[1];
        }
        return parseFloat(number);
    }

    /**
     * formatCurrency
     *
     * @param integer n: number to format
     * @param integer c: length of decimal numbers
     * @param mixed   d: decimal delimiter
     * @param mixed   t: section delimiter
     */
    function formatCurrency(n, c, d, t){
        var c = isNaN(c = Math.abs(c)) ? 2 : c,
            d = d == undefined ? "," : d,
            t = t == undefined ? "." : t,
            s = n < 0 ? "-" : "",
            i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
            j = (j = i.length) > 3 ? j % 3 : 0;
        return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
    };

    /**
     * formatInt
     *
     * @param integer n: number to format
     * @param mixed   t: section delimiter
     */
    function formatInt(n, t){
        var t = t == undefined ? "." : t,
            s = n < 0 ? "-" : "",
            i = parseInt(n = Math.abs(+n || 0).toFixed(0)) + "",
            j = (j = i.length) > 3 ? j % 3 : 0;
        return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t);
    };

    /**
     * formattedDateToTimestamp
     *
     * @param string date
     * @return integer
     */
    function formattedDateToTimestamp(date) {
        var tstamp = 0;
        var expl = date.split('.');
        if (expl.length == 3) {
            tstamp = (new Date(expl[2], expl[1] - 1, expl[0])).getTime();
        }

        return tstamp;
    }

    function PxForm(el){
        this.$formEl = $(el);
        this.bindEvents();
    }

    PxForm.prototype.$formEl = undefined;

    PxForm.prototype.submitted = false;

    PxForm.prototype.validateSelect = function($item){
        if($item.hasClass('js-required') && !$item.val()){
            if($item.attr('data-error-selector')){
                $($item.attr('data-error-selector')).addClass('has-error');
            }else{
                $item.closest('div.form-group').addClass('has-error');
            }
            return false;
        }

        if($item.hasClass('js-active-required') && $item.val() === '' && ($('#' + $item.data('activate-checkbox')).is(':checked') || $('.js-pushed-car-' + $item.data('activate-checkbox') + ':checked').length > 0)){
            if($item.attr('data-error-selector')){
                $($item.attr('data-error-selector')).addClass('has-error');
            }else{
                $item.closest('div.form-group').addClass('has-error');
            }
            return false;
        }

        if($item.attr('data-error-selector')){
            $($item.attr('data-error-selector')).removeClass('has-error');
        }else{
            $item.closest('div.form-group').removeClass('has-error');
        }
        return true;
    };
    PxForm.prototype.validateTextarea = function($item){
        //$item.val($("<div/>").html($item.val()).text());

        //if(($item.hasClass('js-required') && !$item.val()) || ($item.hasClass('js-maxlengthlimit') && $item.val().text().length > jQuery('#js-maxContentCounter').val())){

        var maxlen = jQuery('#js-maxContentCounter').val();
        if ($item.parents('.js-shortDescriptionHolder').length > 0) {
            maxlen = jQuery('#js-maxShortDescriptionCounter').val();
        } else if ($item.data("maxlength")) {
            maxlen = $item.data("maxlength");
        }

        if (isNaN(maxlen)) {
            maxlen = 0;
        }

        var len = $('<div />').html($item.val()).text().length;

        if(($item.hasClass('js-required') && !$item.val()) || ($item.hasClass('js-maxlengthlimit') && len > maxlen)){
            if($item.attr('data-error-selector')){
                $($item.attr('data-error-selector')).addClass('has-error');
            }else{
                $item.closest('div.textedit, div.form-group').addClass('has-error');
            }
            return false;
        }

        if($item.attr('data-error-selector')){
            $($item.attr('data-error-selector')).removeClass('has-error');
        }else{
            $item.closest('div.textedit, div.form-group').removeClass('has-error');
        }

        return true;
    };
    PxForm.prototype.validateText = function($item){
        var val = $item.val(), valid = true;
        if($item.hasClass('js-required') && (!val || ($item.hasClass('js-currency') && val === '0,00'))){
            valid = false;
        }


        if($item.hasClass('js-active-required') && (!val || val === '' || ($item.hasClass('js-currency') && val === '0,00') || ($item.hasClass('js-tyre-select') && val === '') || ($item.hasClass('js-number') && val === '0')) && ($('#' + $item.data('activate-checkbox')).is(':checked') || $('.js-pushed-car-' + $item.data('activate-checkbox') + ':checked').length > 0)) {
            valid = false;
        }

        if(val !== '' && valid){
            if($item.hasClass('js-phone')){
                valid = regex.phone.test(val);
            }else if($item.hasClass('js-email')){
                valid = regex.email.test(val);
            }else if($item.hasClass('js-date')){
                valid = regex.date.test(val);
                if(valid){
                    var expl = val.split('.');
                    var d = expl[2]+'-'+expl[1]+'-'+expl[0];
                    if($item.attr('data-min-today')){
                        var today = new Date();
                        //today = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
                        today = today.getFullYear()+'-'+(today.getMonth()+1 < 10 ? '0'+(today.getMonth()+1) : today.getMonth()+1)+'-'+(today.getDate()<10 ? '0'+today.getDate() : today.getDate());
                        if(d<today){
                            valid = false;
                        }
                    }
                    if ($item.attr('data-min-date')) {
                        if(d<$item.attr('data-min-date')){
                            valid = false;
                        }
                    }
                    if ($item.attr('data-max-date')) {
                        if(d>$item.attr('data-max-date')){
                            valid = false;
                        }
                    }
                    if ($item.attr('data-min-date-selector')) {
                        var $otherElem = $($item.attr('data-min-date-selector'));
                        $otherElem.each(function () {
                            if (regex.date.test($(this).val())) {
                                var lTstamp = formattedDateToTimestamp(val),
                                    oTstamp = formattedDateToTimestamp($(this).val());
                                if (lTstamp < oTstamp) {
                                    valid = false;
                                }
                            }
                        });
                    }
                    if ($item.attr('data-max-date-selector')) {
                        var $otherElem = $($item.attr('data-max-date-selector'));
                        $otherElem.each(function () {
                            if (regex.date.test($(this).val())) {
                                var lTstamp = formattedDateToTimestamp(val),
                                    oTstamp = formattedDateToTimestamp($(this).val());
                                if (lTstamp > oTstamp) {
                                    valid = false;
                                }
                            }
                        });
                    }
                }
            }else if($item.hasClass('js-image')){
                valid = regex.image.test(val);
            }else if($item.hasClass('js-url')){
                valid = regex.url.test(val);
            }else if($item.hasClass('js-number')){
                valid = regex.number.test(val);
            }else if($item.hasClass('js-currency')){
                valid = regex.currency.test(val);
            }else if($item.hasClass('js-zip')){
                valid = regex.zip.test(val);
            }else if($item.hasClass('js-no-digits')){
                valid = !regex.digit.test(val);
            }else if($item.hasClass('js-no-specials')){
                valid = regex.name.test(val);
            }else if($item.hasClass('js-license-plate')){
                valid = regex.licenseplate.test(val);
            }else if($item.hasClass('js-only-digits')){
                valid = onlyNumbers.test(val);
            }else if($item.hasClass('js-house-nr')) {
                valid = regex.housenumber.test(val);
            }
            if($item.attr('data-min-length')){
                if(val.length < $item.attr('data-min-length')){
                    valid = false;
                }
            }

            if($item.attr('data-max-length')){
                if(val.length > $item.attr('data-max-length')){
                    valid = false;
                }
            }
        }
        var $errorItem = $item.closest('div.form-group');
        if($errorItem.length===0){
            $errorItem = $item;
        }
        if(!valid){
            if($item.attr('data-error-selector')){
                $($item.attr('data-error-selector')).addClass('has-error');
            }else{
                $errorItem.addClass('has-error');
            }
        }else{
            if($item.attr('data-error-selector')){
                $($item.attr('data-error-selector')).removeClass('has-error');
            }else{
                $errorItem.removeClass('has-error');
            }
        }
        return valid;
    };
    PxForm.prototype.validateRadio = function($item){
        var val = this.$formEl.find('input[type=radio][name="'+$item.attr('name')+'"]:checked').val();
        if($item.hasClass('js-required') && !val){
            if($item.attr('data-error-selector')){
                $($item.attr('data-error-selector')).addClass('has-error');
            }else{
                $item.closest('div.radio').addClass('has-error');
            }
            return false;
        }
        if($item.attr('data-error-selector')){
            $($item.attr('data-error-selector')).removeClass('has-error');
        }else{
            this.$formEl.find('input[type=radio][name="'+$item.attr('name')+'"]').closest('div.radio').removeClass('has-error');
        }
        return true;
    };
    PxForm.prototype.validateCheckbox = function($item){
        if($item.hasClass('js-checkboxGroup') && $item.hasClass('js-required')){
            var $group = $('.js-checkboxGroup[data-group="'+$item.attr('data-group')+'"]'),
                atleastOneChecked = false;
            $group.each(function(){
                if($(this).prop('checked')){
                    atleastOneChecked = true;
                }
            });
            if(!atleastOneChecked){
                if($item.attr('data-error-selector')){
                    $($item.attr('data-error-selector')).addClass('has-error');
                }else{
                    $group.each(function(){
                        $(this).closest('div.checkbox').addClass('has-error');
                    });
                }
                return false;
            }
        }else if($item.hasClass('js-required') && !$item.prop('checked')){
            if($item.attr('data-error-selector')){
                $($item.attr('data-error-selector')).addClass('has-error');
            }else{
                $item.closest('div.checkbox').addClass('has-error');
            }
            return false;
        }
        if($item.attr('data-error-selector')){
            $($item.attr('data-error-selector')).removeClass('has-error');
        }else{
            $item.closest('div.checkbox').removeClass('has-error');
        }
        if($item.hasClass('js-check-dependencies')){
            var self = this, hasError = false;

            $('input[data-activate-checkbox='+$item.attr('id')+']').each(function(){
                if(!self.validateItem(this)){
                    hasError = true;
                }
            });

            if(hasError && $item.attr('data-collapse-selector')){
                $($item.attr('data-collapse-selector')).collapse('show');
            }
        }

        if($item.hasClass('js-check-filialen')){
            var self = this, hasError = false;
            $('input[data-activate-checkbox='+$item.data('iterator')+']').each(function(){
                if(!self.validateItem(this)){
                    hasError = true;
                }
            });

            if(hasError && $item.attr('data-collapse-selector')){
                $($item.attr('data-collapse-selector')).collapse('show');
            }
        }
        return true;
    };
    PxForm.prototype.validateItem = function(item){
        $item = $(item);
        switch($item.get(0).nodeName.toLowerCase()){
            case 'input':
                switch($item.attr('type').toLowerCase()){
                    default:
                    case 'hidden':
                    case 'text':
                        return this.validateText($item);
                        break;
                    case 'radio':
                        return this.validateRadio($item);
                        break;
                    case 'checkbox':
                        return this.validateCheckbox($item);
                        break;
                    case 'submit':
                        return true;
                        break;
                }
                break;
            case 'select':
                return this.validateSelect($item);
                break;
            case 'textarea':
                return this.validateTextarea($item);
                break;
        }
        return false;
    };

    PxForm.prototype.validateForm = function(){
        var actionEl = this.$formEl.find('input[name="tx_partnerseiten_pi1[data][action]"]');
        if(actionEl){
            if(actionEl.val() == 'delete'){
                return true;
            }
        }
        var self = this;
        var valid = true;
        this.$formEl.find('input, textarea, select').each(function(){
            valid = self.validateItem(this) === false ? false : valid;
        });

        if($('.container.startSlider').length > 0) {
            // Mask with teaser edit form must check whether all slide checkboxes are unchecked,
            // in this case it selects the first checkbox as the default automatically
            var atLeastOneCheckboxSelected = false;
            $('.container.startSlider .js-activeSlide').each(function(id) {
                if(!atLeastOneCheckboxSelected) {
                    if($(this).prop('checked')) atLeastOneCheckboxSelected = true;
                }
            });

            if(!atLeastOneCheckboxSelected) $('.container.startSlider .js-activeSlide').first().prop('checked', true);
        }

        return valid;
    };

    PxForm.prototype.formatGermanCurrency = function($el){
        var val = $el.val();
        if(!regex.currency.test(val)){
            var number = parseNumber(val);
            $el.val(formatCurrency(number));
        }
    };

    PxForm.prototype.formatThousands = function($el){
        var val = $el.val();
        if(onlyNumbers.test(val) || ! regex.number.test(val)){
            var number = parseNumber(val);
            $el.val(formatInt(number));
        }
    };

    PxForm.prototype.bindEvents = function(){
        var self = this;

        this.$formEl.find('input[type=checkbox].js-toggleGroup, input[type=radio].js-toggleGroup').each(function(){
            var $el = self.$formEl.find($(this).attr('data-ref'));
            $(this).on('click', function(){
                if($(this).prop('checked')){
                    $el.removeClass('hidden');
                }else{
                    $el.addClass('hidden');
                }
            });
            if($(this).prop('checked')){
                $el.removeClass('hidden');
            }else{
                $el.addClass('hidden');
            }
        });

        this.$formEl.find('input[type=text].js-datepicker').each(function(){
            var $loc = $(this);

            var minDate = new Date(),
                maxDate = "+1y";

            if($loc.hasClass('js-allowPast')) {
                minDate = null;
            }

            if($loc.attr('data-min-date')){
                var expl = $loc.attr('data-min-date').split('-');
                if(expl.length == 3){
                    minDate = new Date(expl[0], expl[1]-1, expl[2]);
                }
            }
            if($loc.attr('data-max-date')){
                var expl = $loc.attr('data-max-date').split('-');
                if(expl.length == 3){
                    maxDate = new Date(expl[0], expl[1]-1, expl[2]);
                }
            }

            if($loc.attr('data-min-today')){
                var tmpMin = new Date();
                minDate = tmpMin.getTime() > minDate.getTime() ? tmpMin : minDate;
            }

            $loc.datepicker({
                dateFormat: "dd.mm.yy",
                dayNamesMin: [ "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" ],
                monthNames: [ "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember" ],
                defaultDate: new Date(),
                firstDay: 1,
                minDate: minDate,
                maxDate: maxDate,
                showWeek: true,
                weekHeader: "KW",
                showOptions: { direction: "down" },
                autoSize: true,
                closeText: "Schließen",
                currentText: "Heute",
                beforeShow: function(input, inst){
                    if($(input).val() === ''){
                        $(input).val($.datepicker.formatDate("dd.mm.yy",new Date(new Date().getTime() + 24 * 60 * 60 * 1000)));
                    }
                }
            });
            $loc.parent().find('.input-group-addon').on('click',function(){
                $loc.datepicker( "show" );
            });
        });

        this.$formEl.find('.js-formatThousands').each(function(){
            if($(this).val()){
                self.formatThousands($(this));
            }
        });

        this.$formEl.find('input,textarea,select,.jqte_editor').on('blur change',function(){
            var $this = $(this);

            if($this.hasClass('jqte_editor')) {
                $this = $('#'+$this.parent().find('textarea')[0].id)
            }
            if($this.hasClass('js-formatGermanCurrency')){
                self.formatGermanCurrency($this);
            }
            if($this.hasClass('js-formatThousands')){
                self.formatThousands($this);
            }
            self.validateItem($this);
        });

        this.$formEl.on('submit', function(e){
            if(self.submitted || !self.validateForm()){
                e.preventDefault();
                var $firstErrorEl = self.$formEl.find('.has-error:first');

                if ($firstErrorEl.length > 0 ) {

                    if($firstErrorEl.parents('.fancybox-inner').length > 0) {

                        $('.fancybox-inner').scrollTop($firstErrorEl.scrollTop());
                    } else {
                        // OPen parent panel an then scroll to
                        if($firstErrorEl.parents('.panel-collapse')) {
                            $firstErrorEl.parents('.panel-collapse').collapse('show');
                            setTimeout(function() {
                                $('html,body').scrollTop($firstErrorEl.offset().top);
                            }, 300);

                        } else {
                            $('html,body').scrollTop($firstErrorEl.offset().top);
                        }

                    }
                }
            }else{
                self.submitted = true;
                if((self.$formEl.hasClass('js-loadingOverlay') || self.$formEl.find('.js-saveButton').length !== 0) && !e.defaultPrevented){
                    window.pxLoader.startLoading('pxform');
                }
            }
        });
    };

    $(document).ready(function(){
        $(".js-pxform").each(function(){
            forms.push(new PxForm(this));
        });
    });

    window.addPXForm = function(selector){
        $form = $(selector);
        if($form.length > 0 && $form[0].nodeName.toLowerCase() === 'form'){
            forms.push(new PxForm($form));
        }
    };

})(jQuery);
