(function($){
    "use strict";

    // for registering renderer
    $.pixeRegisterElementRenderer = function(slug, render){
        if( pixeData.elements[slug] ){
            pixeData.elements[slug].render = render;
        }
    }
    $.pixeRegisterElementData = function(slug, type){
        if( pixeData.elements[slug] ){
            pixeData.elements[slug].data = type;
        }
    }
    $.pixeRegisterElementFilter = function(slug, callback){
        if( pixeData.elements[slug] && typeof(callback) == 'function' ){
            pixeData.elements[slug].toolbar = callback;
        }
    }

    // item
    $.fn.pixeItem = function(){
        var editor = $(this);
        $.pixeItem.bindToolbar(editor);

        // toolbar position
        editor.on('mouseenter', '.pixe-item', function(){
            var item = $(this);

            if( item.offset().left + 150 > window.innerWidth ){
                item.addClass('pixe-right-toolbar');
            }else{
                item.removeClass('pixe-right-toolbar');
            }
        });
    }

    $.pixeItem = {

        create: function(settings = {}, render = true, preview = false, container){
            settings = $.extend({
                _type: 'element'
            }, settings);

            var t = this;
            var item = $('<div class="pixe-item" ></div>');
            item.addClass('pixe-item-' + settings._element);
            item.data('settings', settings);
            if( container ){
                container.append(item);
            }

            // check for data type
            if( pixeData.elements[settings._element] && pixeData.elements[settings._element].data ){ 
                item.addClass('pixe-data-' + pixeData.elements[settings._element].data); 
            }

            // toolbar
            if( preview ){
                item.data('preview', true);
            }else{
                item.append(t.getToolbar(item));
            }
            item.append('<style></style>');

            // item dependency
            $.pixeAddDependency(item, settings._element);

            if( pixeData.elements[settings._element] && pixeData.elements[settings._element].deps ){
                for( var i in pixeData.elements[settings._element].deps ){
                    var dep = pixeData.elements[settings._element].deps[i];
                    $.pixeAddDependency(item, dep);
                }
            }

            // set id
            if( settings._id ){ item.attr('data-id', settings._id); }
            if( settings.id ){ item.attr('id', settings.id); }

            // content area
            item.append('<div class="pixe-item-content" ></div>');

            if( !preview ){

                // bottom padding
                item.append('<div class="pixe-item-padding-resize pixe-bottom" ></div>');

                // item area
                item.append('<div class="pixe-item-area"></div>');

                // toolbar mod
                if( pixeData.elements[settings._element] && pixeData.elements[settings._element].toolbar ){
                    pixeData.elements[settings._element].toolbar(item);
                }
            }

            if( pixeData.elements[settings._element] && pixeData.elements[settings._element].isPro && 
                    (typeof(pixePP) === 'undefined' || !pixePP.active) ){
                item.addClass('pixe-locked');
            }
            
            // render content
            if( render ){ t.render(item); }

            return item;
        },
        render: function(item, type){
            var t = this;
            if( type ){
                t.renderStyle(item, type);
                return;
            } 

            t.renderStyle(item, 'item', undefined, true);
        },
        renderAjax: function(item, container, ajaxSettings){
            var t = this;

            // for running script data
            if( t.ignoreAjaxRequest ){
                if( ajaxSettings && typeof(ajaxSettings.onUpdate) == 'function' ){
                    ajaxSettings.onUpdate(item.children('.pixe-item-content'));
                }
                return;
            }

            // running normal ajax to retrieve content
            ajaxSettings = $.extend({
                container: container,
                onEmpty: function(){
                    var settings = item.data('settings');
                    var itemType = '(' + settings._element + ')';
                    container.empty().append($.pixePreviewText('Sorry, the content you\'re looking for could not be found. Please activate the corresponding plugin to access this item. ' + itemType));
                }
            }, ajaxSettings);

            function getHtml(){
                var settings = item.data('settings');
                $.pixeGetAjaxContent(settings, ajaxSettings);
            }
            
            if( !container.html() ){
                getHtml();
            }else{
                var htmlRenderer = item.data('html-renderer');
                if( !htmlRenderer ){
                    htmlRenderer =  $.pixeDebounce(getHtml, 500);
                    item.data('html-renderer', htmlRenderer);
                }
                htmlRenderer();
            }
        },
        renderStyle: function(item, type, subtype, renderCss = true){
            if( !item.hasClass('pixe-item') ) return;
            if( !item.data('settings') ) return;

            var t = this;

            // check css for pro featured
            if( !t.proRenderStyle || !t.proRenderStyle(item, type, subtype) ){
                switch(type){
                    case 'class':
                    case 'id':
                    case 'responsive':
                        $.pixeSetAdvanceStyle(item, type);
                        break;
                    case 'default':
                    case 'z-index':
                    case 'position':
                    case 'top':
                    case 'right':
                    case 'bottom':
                    case 'left':
                    case 'tablet-z-index':
                    case 'tablet-position':
                    case 'tablet-top':
                    case 'tablet-right':
                    case 'tablet-bottom':
                    case 'tablet-left':
                    case 'mobile-z-index':
                    case 'mobile-position':
                    case 'mobile-top':
                    case 'mobile-right':
                    case 'mobile-bottom':
                    case 'mobile-left':
                    case 'item-width':
                    case 'item-max-width':
                    case 'tablet-item-width':
                    case 'tablet-item-max-width':
                    case 'mobile-item-width':
                    case 'mobile-item-max-width':
                    case 'align-self':
                    case 'flex-basis':
                    case 'flex-grow':
                    case 'flex-shrink':
                    case 'flex-order':
                    case 'tablet-align-self':
                    case 'tablet-flex-basis':
                    case 'tablet-flex-grow':
                    case 'tablet-flex-shrink':
                    case 'tablet-flex-order':
                    case 'mobile-align-self':
                    case 'mobile-flex-basis':
                    case 'mobile-flex-grow':
                    case 'mobile-flex-shrink':
                    case 'mobile-flex-order':
                    case 'transform':
                    case 'transform-hover':
                    case 'tablet-transform':
                    case 'tablet-transform-hover':
                    case 'mobile-transform':
                    case 'mobile-transform-hover':
                        t.setDefaultCss(item);
                        break;
                    case 'animation':
                    case 'tablet-animation':
                    case 'mobile-animation':
                        $.pixeSetAnimationStyle(item);
                        break;
                    case 'scroll-motion':
                    case 'tablet-scroll-motion':
                    case 'mobile-scroll-motion':
                        $.pixeSetScrollMotionStyle(item);
                        break;
                    case 'hover-animation':
                        $.pixeSetHoverAnimationStyle(item);
                        break;
                    case 'padding':
                    case 'tablet-padding':
                    case 'mobile-padding':
                    case 'margin':
                    case 'tablet-margin':
                    case 'mobile-margin':
                        t.setSpacingStyle(item);
                        break;
                    default:
                        if( type == 'item' ){
                            t.renderStyle(item, 'id', undefined, false);
                            t.renderStyle(item, 'class', undefined, false);
                            t.renderStyle(item, 'responsive', undefined, false);
                            t.renderStyle(item, 'default', undefined, false);
                            t.renderStyle(item, 'padding', undefined, false);
                            t.renderStyle(item, 'animation', undefined, false);
                            t.renderStyle(item, 'hover-animation', undefined, false);
                            t.renderStyle(item, 'pro', undefined, false);
                        }

                        var settings = item.data('settings');
                        if( pixeData.elements[settings._element] && typeof(pixeData.elements[settings._element].render) == 'function' ){
                            pixeData.elements[settings._element].render(item, type, subtype);
                        }else{
                            $.pixeItem.renderAjax(item, item.children('.pixe-item-content'));
                        }
                        break;
                }
            }

            if( renderCss ){
                t.renderCss(item);
            }
        },

        renderCss: function(item){
            var style = item.data('style');
            var extraCss = item.data('extra-style');
            var styleTag = item.children('style');
            $.pixeRenderCss(styleTag, style, extraCss);
        },

        // default css
        setDefaultCss: function(item){
            var settings = item.data('settings');
            var id = '[data-id="' + settings._id + '"]';

            function getCss(deviceSlug = ''){
                var css = '';

                // wrap area
                var atts = {
                    'transform': settings[deviceSlug + 'transform'],
                    'align-self': settings[deviceSlug + 'align-self'],
                    'flex-basis': settings[deviceSlug + 'flex-basis'],
                    'flex-grow': settings[deviceSlug + 'flex-grow'],
                    'flex-shrink': settings[deviceSlug + 'flex-shrink'],
                    'order': settings[deviceSlug + 'flex-order'],
                    'width': settings[deviceSlug + 'item-width'],
                    'max-width': settings[deviceSlug + 'item-max-width'],
                    'position': settings[deviceSlug + 'position'],
                    'z-index': settings[deviceSlug + 'z-index']
                };

                if( settings['scroll-motion'] && settings['scroll-motion']['enable'] ){
                    if( !deviceSlug ){
                        atts['position'] = 'absolute';
                        atts['width'] = !atts['width']? 'auto': atts['width'];
                        atts['top'] = settings['top']? settings['top']: '0px';
                        atts['right'] = settings['right'];
                        atts['left'] = settings['left'];
                        if( !atts['left'] && !atts['right'] ){
                            atts['left'] = '0px';
                        }
                    }else{
                        delete atts['position'];
                        atts['width'] = atts['width'];
                        atts['top'] = settings[deviceSlug + 'top'];
                        atts['right'] = settings[deviceSlug + 'right'];
                        atts['left'] = settings[deviceSlug + 'left'];
                    }
                    $.pixeSetScrollMotionStyle(item);
                }else if( settings[deviceSlug + 'position'] == 'absolute' || settings[deviceSlug + 'position'] == 'fixed' ){
                    atts['width'] = !atts['width']? 'auto': atts['width'];
                    atts['top'] = settings[deviceSlug + 'top'];
                    atts['right'] = settings[deviceSlug + 'right'];
                    atts['bottom'] = settings[deviceSlug + 'bottom'];
                    atts['left'] = settings[deviceSlug + 'left'];
                }

                css += $.pixeSetCss(id, atts);

                // wrap hover area
                css += $.pixeSetCss($.pixeGetHoverSelector(id + ':hover', item), {
                    'transform': settings[deviceSlug + 'transform-hover']
                });

                return css;
            }

            // apply css
            $.pixeAddCss(item, 'default', getCss());
            $.pixeAddCss(item, 'default', getCss('tablet-'), 'tablet');
            $.pixeAddCss(item, 'default', getCss('mobile-'), 'mobile');
        },

        // spacing
        setSpacingStyle: function(item){
            var settings = item.data('settings');
            $.pixeSetSpacingStyle(item, settings);
        },
        
        // toolbar
        getToolbar: function(item){
            var settings = item.data('settings');
            var iconPrefix = 'item';
            if( item.hasClass('pixe-data-tab') ){
                iconPrefix = 'wrapper';
            }

            var html  = '<div class="pixe-item-toolbar" >';
                html += '<div class="pixe-action pixe-drag" ><div class="pixe-svg-preset pixe-svg-' + iconPrefix + '-drag"></div></div>';
                if( pixeData.elements[settings._element] && pixeData.elements[settings._element].isPro && 
                    (typeof(pixePP) === 'undefined' || !pixePP.active) ){
                    // do nothing
                }else{
                    html += '<div class="pixe-action pixe-maximize pixe-svg-preset pixe-svg-' + iconPrefix + '-spaces" ></div>';
                    html += '<div class="pixe-action pixe-copy pixe-svg-preset pixe-svg-' + iconPrefix + '-copy" ></div>';
                }
                html += '<div class="pixe-action pixe-settings pixe-svg-preset pixe-svg-' + iconPrefix + '-settings" ></div>';
                html += '<div class="pixe-action pixe-close pixe-svg-preset pixe-svg-' + iconPrefix + '-trash" ></div>';
                html += '</div>';
    
            return html;
        },

        remove: function(item, updateNavigator = true){

            function remove(){
                var parent = item.parent();

                // save for history
                var action = $.pixeHistory.createAction(item, 'remove');
                
                // remove dom
                item.detach();

                // add history action
                $.pixeHistory.addAction(action, updateNavigator);

                // check parents status
                if( parent.hasClass('pixe-editor') ){
                    $.pixeEditor.setStatus();
                }else{
                    var container = parent.closest('.pixe-tab-container, .pixe-column, .pixe-wrapper, .pixe-editor');
                    $.pixeEditor.setStatus(container);
                }
            }

            // ask before remove on mobile/tablet devices
            if( $.pixeEditor.viewport == 'desktop' ){
                remove();
            }else{
                $.pixeConfirmationBox({
                    extraClass: 'pixe-red',
                    title: 'Remove Element',
                    confirmText: 'Remove',
                    message: 'Please note that removing an element while editing in Tablet or Mobile view will also remove it from the Desktop view and across all devices.',
                    onSuccess: function(){
                        remove();
                    }
                });
            }

        },

        bindToolbar: function(editor){
            var t = this;
            
            editor.on('click', '.pixe-item-toolbar .pixe-action', function(){
                var item = $(this).closest('.pixe-item');

                // edit settings
                if( $(this).hasClass('pixe-settings') ){
                    pixeData.hideBuilderPanel = false;
                    
                    if( $.pixeEditor.viewport == 'desktop' ){
                        $.pixeEditor.setEditTarget(item); 
                    }else{
                        $.pixeEditor.setEditTarget(item, ['style', 'spacing']); 
                    }
                    
                
                }else if( $(this).hasClass('pixe-maximize') ){

                    $.pixeSpacingPopup(item, {
                        button: $(this),
                        type: 'tbpdpx',
                        focusClass: 'pixe-focus pixe-focus-toolbar', 
                        onChange: function(type){
                            t.renderStyle(item, type);
                        }
                    });

                // remove item
                }else if( $(this).hasClass('pixe-close') ){

                    t.remove(item);
                    
                // duplicate item
                }else if( $(this).hasClass('pixe-copy') ){
                    
                    // copy & assign unique id
                    var settings = $.pixeClone($.pixeGetEditorVal(item));
                    $.pixeEditor.setUniqueIdData(settings);

                    // set unique id
                    var newItem = t.create(settings);
                    newItem.insertAfter(item);
                    t.render(newItem);

                    // save for history
                    var action = $.pixeHistory.createAction(newItem, 'duplicate');
                    $.pixeHistory.addAction(action);
                }

            });

            // padding resize
            editor.pixeDragResize({
                selector: '.pixe-item-padding-resize',
                itemSelector: '.pixe-item',
                onResize: function(item, handler, diff){
                    $.pixeSetPaddingDiff(item, handler, diff, false);
                    t.renderStyle(item, 'padding');
                }
            });
        },

        // is tab empty
        setTabContainerStatus: function(container){
            if( !container.hasClass('pixe-tab-container') ) return;

            if( container.children().length ){
                container.removeClass('pixe-empty');
            }else{
                container.addClass('pixe-empty');
            }
        }

    }

})(jQuery);	