var ContentTypeFormManager = (function() {
    'use strict';

    /**
     * @constructor
     */
    function ContentTypeFormManager() {
        this.editable = false;
        this.allowEmptyData = false;
    }

    /**
     * Function for init the features of form.
     */
    ContentTypeFormManager.prototype.init = function() {
        FormEditable.init();
        ComponentsFormTools.init();

        this.initCollection();
        this.appendChildrenInLoops();
        this.initInlineEditableFields($('body'));
        this.initSelectsBehaviour();
        this.preSubmitActions();
        this.replaceRequiredAttrToData();
        this.initDomBindings();
    };

    /**
     * Init the SimpleFormCollection.
     */
    ContentTypeFormManager.prototype.initCollection = function() {
        var options = {
            'addElement' : '[data-add="group"]',
            'deleteElement' : '[data-delete="group"]'
        };
        var _this = this;

        options[SimpleFormCollection.AFTER_ADD] = function(element) {
            _this.initInlineEditableFields(element);
            _this.initSelect2(element);
            _this.initSwitch(element);
            _this.initMultipleCollection(element);
            _this.replaceRequiredAttrToData();
        };

        options[SimpleFormCollection.REMOVE] = function(element) {
            _this.removeGroup(element, this);
        };


        $('[data-collection="content-group"]').SimpleFormCollection(options);
    };

    /**
     * Init the MultiplePrototypeFormCollection
     *
     * @param {jQuery} element
     */
    ContentTypeFormManager.prototype.initMultipleCollection = function(element) {
        var addFieldSelector = '[data-add="field"]',
            addLoopSelector = '[data-add="loop"]';

        var options = {
            'addElementSelectors' : [addFieldSelector, addLoopSelector],
            'dataSelectors' : ['prototype-single', 'prototype-loop'],
            'deleteElementSelector' : '[data-delete="field"]',
            'context' : element,
            'prototypeFieldName' : '__NAME_FIELD__'
        };

        var _self = this;
        var collectionElement =  $('[data-collection="fields"]', element);

        options[SimpleFormCollection.AFTER_ADD] = function(element) {
            var _this = this;

            _self.initInlineEditableFields(element);
            _self.initSelect2(element);
            _self.initSwitch(element);
            _self.initSortables();
            _self.replaceRequiredAttrToData();

            if($(element).data('field') === 'loop') {
                var guid  = $(element).data('uuid')||ComitiumUtils.generateGUID();

                $(element).data('guid', guid);

                _self.assignParentId(element, guid);

                $('[data-add="field"]', element).off('click').on('click', function(event) {
                    event.preventDefault();
                    var previousContainer = _this.collectionContainer;
                    _this.collectionContainer = $('[data-collection]', element);

                    var callback = function(element) {
                        _self.assignParentId(element, guid);
                    };

                    _this.addHandler(SimpleFormCollection.AFTER_ADD, callback, true);

                    $('[data-add="field"]:first', _this.context).trigger('click');
                    _this.collectionContainer = previousContainer;
                });

                if($('[data-collection]', element).children().length === 0 && !$(element).data('persisted')) {
                    $('[data-add="field"]', element).trigger("click");
                }
            }
        };

        options[SimpleFormCollection.REMOVE] = function(element) {
            var collection = this;
            if($(element).data('field') === 'loop') {
                _self.removeLoop(element, this);
            } else {
                _self.removeField(element, this);
            }

        };

        collectionElement
            .MultiplePrototypeFormCollection(options);

        if(collectionElement.children().length <= 0) {
            $(element)
                .find('[data-add="field"]')
                .trigger('click');
        }

        $(element)
            .find('[data-target]')
            .first()
            .trigger('click');
    };

    /**
     * Init the editable fields of element.
     *
     * @param {jQuery} element
     */
    ContentTypeFormManager.prototype.initInlineEditableFields = function(element) {
        $(element)
            .find('.groupname, .fieldname').editable({
                validate: function (value) {
                    if ($.trim(value) == '') {
                        return Translator.trans('cs_common_base.form.messages.errors.required');
                    }
                    else{
                        $('#'+$(this).data('for')).val(value);
                    }
                },
                mode: 'inline'
            })
            .on('click', function(){
                $('.editable-input :first-child').select().addClass('form-control');
            })
        ;
    };

    /**
     * Init the select2 of element.
     *
     * @param {jQuery} element
     */
    ContentTypeFormManager.prototype.initSelect2 = function(element) {
        $(element).find('select').each(function(){
            $(this).select2();
        });
    };

    /**
     * Bind pre-submit actions.
     */
    ContentTypeFormManager.prototype.preSubmitActions = function(){
        var _self = this;
        $('form').on('submit', function(e) {
            //e.preventDefault();
            var success = true;

            // Order groups
            $('[id$="position"][data-type="group"]', $(this)).each(function(k){
                $(this).val(k+1);
            });

            //Order fields
            $('[id$="position"][data-type="field"]', $(this)).each(function(k){
                $(this).val(k+1);
            });

            success = _self.validateFields();

            if(success) {
                $('select[disabled], input[disabled]').each(function(k,v){
                    $(v).prop('disabled', false);
                });
            }

            return success;
        });
    };

    /**
     * Init switch checkbox of element.
     *
     * @param {jQuery} element
     */
    ContentTypeFormManager.prototype.initSwitch = function(element) {
        $(element).find('[type="checkbox"]').each(function () {
            $(this).bootstrapSwitch();
        });
    };

    /**
     * @param {boolean} editable
     */
    ContentTypeFormManager.prototype.setEditable = function(editable) {
        this.editable = editable;
    };

    /**
     * @param {boolean} editable
     */
    ContentTypeFormManager.prototype.setAllowEmptyData = function(allowEmptyData) {
        this.allowEmptyData = allowEmptyData;
    };

    /**
     * Init the selects behaviour on change.
     */
    ContentTypeFormManager.prototype.initSelectsBehaviour = function() {
        $(document).on('change','select', function(){
            var arr = $(this).attr('data-length-fields').split(',');
            var value = $(this).find(':selected').data('field');
            var target = $(this).closest('[data-field="field"]').find('[data-type="length"]');

            if (target.length) {

                if ($.inArray(value.toString(), arr) != -1 ) {
                    target.attr('disabled', false).val(1);
                    target.closest('div').show();
                } else {
                    target.closest('div').hide();
                    target.attr('disabled', true).val(1);
                }
            }

            if (value == 114) {
                _entityHtmlInit($(this), true);
            } else {
                _entityHtmlInit($(this), false);
            }

        });
    };

    var _entityHtmlInit = function(select, show) {
        var _container   = select.parents('[data-container="entity-type"]');
        var _description = _container.find('[data-semantic="description"]');
        var _hidden = _container.find('[data-semantic="entity"]');

        if (show) {
            _description.removeClass("col-md-4");
            _description.addClass("col-md-12");
            _description.insertAfter(_container.children(":nth-child(6)"));
            _hidden.show();
        } else {
            _description.removeClass("col-md-12");
            _description.addClass("col-md-4");
            _description.insertAfter(_container.children(":nth-child(2)"));
            _hidden.hide();
        }

    };

    /**
     * Init sortable feature.
     */
    ContentTypeFormManager.prototype.initSortables = function() {
        //When implement connect sortable, discomment connectWith .
        $('[data-collection]').sortable({
            placeholder: 'portlet-sortable-placeholder',
            forcePlaceholderSize: true
            //connectWith: '[data-collection]'
        });
    };

    /**
     *
     * @param {jQuery|HTMLElement} element
     * @param {string} guid
     * @returns {ContentTypeFormManager}
     */
    ContentTypeFormManager.prototype.assignParentId = function(element, guid) {
        $(element).find('input[id$="_parentUuid"]').val(guid);

        return this;
    };

    /**
     * Change the required attr of form elements with data-required for manual validation.
     */
    ContentTypeFormManager.prototype.replaceRequiredAttrToData = function() {
        $('[required]', '[data-role="dynamic-fields-container"]')
            .removeAttr('required')
            .attr('data-required', 'required');
    };

    /**
     * Bind custom dom events.
     */
    ContentTypeFormManager.prototype.initDomBindings = function() {
        $('form')
            .on('hidden.bs.collapse', '[data-field="field"]', function() {

                var element = $('[data-update]', this).fadeIn();
                var persisted = $(this).data('persisted');
                var infoInputs = element.data('update').split(',');
                var info = [];
                $.each(infoInputs, function(index, value) {
                    var element = $(value);
                    if(element.is(':visible')) {
                        var placeholder = '';

                        if(element.is('select')) {
                            placeholder = $('option:selected', element).text();
                        } else if(element.is(':checkbox')) {
                            if(element.is(':checked')) {
                                placeholder = element.data('text-checked');
                            } else {
                                placeholder = element.data('text-unchecked');
                            }
                        } else {
                            placeholder = element.val();
                        }

                        if(placeholder !== '' && (!element.is(':disabled') || persisted)){
                            info.push(placeholder);
                        }
                    }
                });

                if(info.length > 0) {
                    element.html(info.join(' / '));
                }
            })
            .on('show.bs.collapse', '[data-field="field"]', function() {
                $('[data-update]', this).fadeOut();
            });
    };

    /**
     * Function for put loop fields into loop
     */
    ContentTypeFormManager.prototype.appendChildrenInLoops = function() {
        $('[data-field="loop"]').each(function() {
            $('input[value="'+$(this).data('uuid')+'"][id$="_parentUuid"]')
                .closest('[data-field="field"]')
                .appendTo($('[data-collection]', this));
        });
    };

    /**
     * Remove group of collection callback.
     *
     * @param {jQuery} element
     * @param {SimpleFormCollection|MultiplePrototypeFormCollection}collection
     */
    ContentTypeFormManager.prototype.removeGroup = function(element, collection) {
        var groupName = this.getElementName($('.accordion', element)) || '';

        if($('[data-group="group"]').length > 1 || this.allowEmptyData === true) {
            var modal = this.initModal(Translator.trans('contentType.dynamicFields.modals.group.title'), Translator.trans('contentType.dynamicFields.modals.group.message', {'name': groupName}))
                .find('[data-btn-type="save"]')
                .on("click", function () {
                    collection.removeElement(element);
                    modal.modal('hide');
                })
                .end();
        } else {
            showToastrNotification('error', Translator.trans('contentType.dynamicFields.errors.lastGroup', {'name': groupName}));
        }
    };

    /**
     * Remove Loop callback.
     *
     * @param {jQuery} element
     * @param {SimpleFormCollection|MultiplePrototypeFormCollection} collection
     */
    ContentTypeFormManager.prototype.removeLoop = function(element, collection) {
        var _self = this;
        var loopCollectionContainer = _self.getLoopCollectionContainer(element);
        var numElements = collection.collection.length - _self.getNumberOfFieldsInLoop(loopCollectionContainer);
        var loopName = _self.getElementName($('.loop-title', element)) || '';

        if(numElements > 1) {
            var modal = this.initModal(Translator.trans('contentType.dynamicFields.modals.loop.title'), Translator.trans('contentType.dynamicFields.modals.loop.message', {'name': loopName}))
                .find('[data-btn-type="save"]')
                .on("click", function () {
                    var fields = _self.getFieldsInLoop(loopCollectionContainer);

                    fields.each(function(){
                        collection.removeElement(this);
                    });

                    collection.removeElement(element);
                    modal.modal('hide');
                })
                .end();
        } else {
            showToastrNotification('error', Translator.trans('contentType.dynamicFields.errors.lastLoop', {'name' : loopName}));
        }
    };

    /**
     * Remove field callback.
     *
     * @param {jQuery} element
     * @param {SimpleFormCollection|MultiplePrototypeFormCollection} collection
     */
    ContentTypeFormManager.prototype.removeField = function(element, collection) {

        var fieldName = this.getElementName($('.accordion', element)) || '';
        if($(element).data('persisted')) {
            if(!this.isLoopField(element) || this.getNumberOfFieldsInLoop(this.getLoopCollectionContainerByField(element)) > 1) {
                if(collection.collection.length > 1) {
                    var modal = this.initModal(Translator.trans('contentType.dynamicFields.modals.field.title'), Translator.trans('contentType.dynamicFields.modals.field.message', {'name': fieldName}))
                        .find('[data-btn-type="save"]')
                        .on("click", function () {
                            collection.removeElement(element);
                            modal.modal('hide');
                        })
                        .end();
                } else {
                    showToastrNotification('error', Translator.trans('contentType.dynamicFields.errors.lastField', {'name': fieldName}));
                }
            } else {
                showToastrNotification('error', Translator.trans('contentType.dynamicFields.errors.lastField', {'name': fieldName}));
            }
        } else {
            if(!this.isLoopField(element) || this.getNumberOfFieldsInLoop(this.getLoopCollectionContainerByField(element)) > 1) {

                if(collection.collection.length > 1) {
                    collection.removeElement(element);
                } else {
                    showToastrNotification('error', Translator.trans('contentType.dynamicFields.errors.lastField', {'name': fieldName}));
                }

            } else {
                showToastrNotification('error', Translator.trans('contentType.dynamicFields.errors.lastField', {'name': fieldName}));
            }
        }
    };

    /**
     * Get the loop container by loop element.
     *
     * @param {jQuery} element
     * @returns {*|jQuery|HTMLElement}
     */
    ContentTypeFormManager.prototype.getLoopCollectionContainer = function(element) {
        return $(element).find('[data-collection]').first();
    };

    /**
     * Get the loop collection container by field element.
     *
     * @param {jQuery} element
     * @returns {*|jQuery}
     */
    ContentTypeFormManager.prototype.getLoopCollectionContainerByField = function(element) {
        return $(element).closest('[data-collection]').first();
    };

    /**
     * Check if a field is inside a loop
     *
     * @param {jQuery} element
     * @returns {boolean}
     */
    ContentTypeFormManager.prototype.isLoopField = function(element) {
        return this.getLoopCollectionContainerByField(element).data('collection') === 'loop-fields';
    };

    /**
     * Return the number of fields in a loop collection container.
     *
     * @param {jQuery} element The loop collection container
     * @returns {int}
     */
    ContentTypeFormManager.prototype.getNumberOfFieldsInLoop = function(element) {
        return $(element).children('[data-field]').length;
    };

    /**
     * Init a modal with a title and body message.
     *
     * @param {String} title
     * @param {string} message
     * @returns {*}
     */
    ContentTypeFormManager.prototype.initModal = function(title, message) {
        return window.bootstrap.modal.show(title, message, Translator.trans("cs_core.action.accept"));
    };

    /**
     * Get the element name specified in input
     *
     * @param {jQuery} element
     * @returns {String}
     */
    ContentTypeFormManager.prototype.getElementName = function(element) {
        return $(element).children('[id$="_defaultLang_name"]').val();
    };

    /**
     * Return the fields inside a loop collection
     *
     * @param loopCollectionContainer
     * @returns {*|jQuery}
     */
    ContentTypeFormManager.prototype.getFieldsInLoop = function(loopCollectionContainer) {
        return $(loopCollectionContainer).find('[data-field]');
    };

    /**
     * Validates fields of collection
     *
     * @returns {boolean}
     */
    ContentTypeFormManager.prototype.validateFields = function() {
        var success = true;

        $('[data-role="dynamic-fields-container"]').find('[data-required="required"]').each(function(){
            if ($(this).val() == '') {

                if (!($(this).not(":visible") && $(this).is("[id$='_length']"))) {
                    showToastrNotification('error',Translator.trans('contentType.dynamicFields.errors.mandatoryFields'));
                    success = false;
                }
            }
        });

        return success;
    };

    return ContentTypeFormManager;
}());
