(function($) {
    $.widget("qusion.layoutManager", {
        options: {
            mode: 'widget',
            prefix: 'qusion-cms-',
            widgetContent: true,
            wrapIgnore: null,
            layout: {
                wrapper: 'wrapper',
                section: 'section',
                sectionEmpty: 'section-empty',
                sectionHover: 'section-hover',
                widget: 'widget',
                widgetHeader: 'widget-header',
                widgetContent: 'widget-content',
                bar: 'bar',
                placeholder: 'widget-placeholder',
                placeholderEmpty: 'widget-placeholder-empty'
            },
            local: {
                edit: 'Edit',
                more: 'More',
                dropHere: 'Drop here',
                empty: 'No widgets added to this box <span>Add widgets here</span>'
            }
        },
        _create: function() {
            var self = this, options = self.options, element = this.element, toolbox;

            // create wrapper if don't exists and wrap all body content with it
            // scripts tag will be not wrapped
            self.wrapper = element.find(self._cssClass(options.layout.wrapper));
            if (self.wrapper.length == 0) {
                self.wrapper = $('<div />', { 'class': self._prefix(options.layout.wrapper) });
                element.children(':not(script)')
                    .not(self.wrapper)
                    .not(options.wrapIgnore)
                    .not("script")
                    .wrapAll(self.wrapper);
            }

            // find all elements marked as widgets to create sortable widgets
            element.find(self._cssClass(options.layout.widget)).each(function() {
                self._createCmsWidget($(this));
            });

            // create sortable widgets
            var sortable = self.sortables = element.find(self._cssClass(options.layout.section))
                .sortable({
                    connectWith: self._cssClass(options.layout.section),
                    items: self._cssClass(options.layout.widget),
                    forcePlaceholderSize: false,
                    helper: 'clone',
                    opacity: 0.5,
                    distance: 10,
                    handle: self._cssClass(options.layout.widgetHeader),
                    placeholder: self._prefix(options.layout.placeholder),
                    tolerance: 'pointer',
                    sort: function(event, ui) { self._sort(event, ui); },
                    start: function(event, ui) { self._sortStart(event, ui); },
                    stop: function(event, ui) { self._sortStop(event, ui); },
                    receive: function(event, ui) { self._receive(event, ui); },
                    //deactivate: function (event, ui) { el.find('.' + o.css.sectionHover).removeClass(o.css.sectionHover); },
                    update: function(event, ui) { self._update(event, ui); }
                }).disableSelection();

        },
        getSortables: function () {
            return this.sortables;
        },
        _createCmsWidget: function(element) {

            var self = this, options = this.options;

            var model = {
                title: element.data("title"),
                key: element.data("key"),
                scope: element.data("scope")
            };

            // widget content wrapper
            element.wrapInner('<div class="' + self._prefix(options.layout.widgetContent) + '" />');

            // widget header
            var header = $('<div />', { 'class': self._prefix(options.layout.widgetHeader) })
                .prependTo(element);

            $('<div />', { 'class': self._prefix(options.layout.widgetHeader) + '-title', text: model.title })
                .appendTo(header);

            // add clear element to clear floatings
            $('<div class="ui-clear"><!-- --></div>').appendTo(header);
        },
        _refresh: function() {
            var self = this, element = this.element, options = this.options;

            // if there are no widgets in section than mark section as empty
            element.find(self._cssClass(options.layout.section))
                .not(':has("' + self._cssClass(options.layout.widget) + '")')
                .addClass(self._prefix(options.layout.sectionEmpty));

            // if there are widgets inside section than we want to remove section empty css class
            element.find(self._cssClass(options.layout.section))
                .has(self._cssClass(options.layout.widget))
                .removeClass(self._prefix(options.layout.sectionEmpty))
                .find(self._cssClass(options.layout.placeholderEmpty)).remove();

            // every empty section has to contain empty placeholder
            element.find(self._cssClass(options.layout.sectionEmpty)).each(function() {
                $(this).empty();
                $('<div />', { html: options.local.empty })
                    .addClass(self._prefix(options.layout.placeholderEmpty))
                    .appendTo($(this));
            });
        },
        _cssClass: function(input) {
            return "." + this._prefix(input);
        },
        _prefix: function(input) {
            return this.options.prefix + input;
        },
        _receive: function(event, ui) {
            var self = this, element = this.element, options = this.options;
            if (ui.item.hasClass(self._prefix(options.layout.widget)))
                self._trigger('widgetMove', event, ui);

            self._trigger('receive', event, ui);
        },
        _update: function(event, ui) {
            var self = this, element = this.element, options = this.options;
            self._refresh();
            self._trigger('update', event, ui);
        },
        _sort: function(event, ui) {
            var self = this, element = this.element, options = this.options;
            // remove hover class for deactivated element
            element.find(self._cssClass(options.layout.sectionHover))
                .removeClass(self._prefix(options.layout.sectionHover));

            ui.placeholder.parent().addClass(self._prefix(options.layout.sectionHover));
            // trigger sort event
            self._trigger('sort', event, ui);
        },
        _sortStart: function(event, ui) {
            var self = this, element = this.element, options = this.options;
            //// set placeholder text
            ui.placeholder.html(options.local.dropHere);
            // trigger sort start event
            self._trigger('start', event, ui);
        },
        _sortStop: function(event, ui) {
            var self = this, element = this.element, options = this.options;
            // remove hover class for deactivated element
            element.find(self._cssClass(options.layout.sectionHover))
                .removeClass(self._prefix(options.layout.sectionHover));
            ui.placeholder.parent().addClass(self._prefix(options.layout.sectionHover));

            // if toolbox
            if (ui.item.hasClass(self._prefix(options.layout.toolboxWidget))) {
                self._trigger('widgetAdd', event, ui);

                ui.item.remove();
                self._refresh();
            } else if (ui.item.hasClass(self._prefix(options.layout.widget))) {
                self._trigger('widgetMove', event, ui);
            } else {
                // refresh
                self._refresh();
            }
            // trigger sort stop event
            self._trigger('stop', event, ui);
        }
    });
})(jQuery);