/**
* jQuery ligerUI 1.2.3
* 
* http://ligerui.com
*  
* Author daomi 2014 [ gd_star@163.com ] 
* 
*/
(function ($) {

    //manager base
    $.ligerui = $.ligerui || {};
    $.ligerui.addManager = function (dom, manager) {
        if (dom.id == undefined || dom.id == "")
            dom.id = "ligerui" + (1000 + $.ligerui.ManagerCount);
        $.ligerui.ManagerCount++;
        $.ligerui.Managers[dom.id] = manager;
        dom.applyligerui = true;
    };
    $.ligerui.getManager = function (domArr) {
        if (domArr.length == 0) return null;
        return $.ligerui.Managers[domArr[0].id];
    };
    $.ligerui.Managers = $.ligerui.Managers || {};
    $.ligerui.ManagerCount = $.ligerui.ManagerCount || 0;

    $.fn.ligerGetPanelManager = function () {
        return $.ligerui.getManager(this);
    };

    $.ligerDefaults = $.ligerDefaults || {};

    $.ligerDefaults.Portal = {
        width: null,
        /*行元素：组件允许以纵向方式分割为几块
        每一块(行)允许自定义N个列(column)
        每一列允许自定义N个Panel(最小元素)
        rows:[
            {columns:[ 
                {
                   width : '50%',
                   panels : [{width:'100%',content:'内容'},{width:'100%',url:@url1}]
                },{
                   width : '50%',
                   panels : [{width:'100%',url:@url2}]
                }
            ]}
        ]
        */
        rows: null,
        /* 列元素： 组件将认为只存在一个row(块),
       这一块 允许自定义N个列(column),结构同上
        */
        columns: null,
        url: null,          //portal结构定义URL   
        method: 'get',                         //获取数据http方式
        parms: null,                         //提交到服务器的参数
        draggable: false,   //是否允许拖拽
        onLoaded: null       //url模式 加载完事件
    };
    $.ligerDefaults.Portal_rows = {
        width: null,
        height: null
    };
    $.ligerDefaults.Portal_columns = {
        width: null,
        height: null
    };
    $.ligerManagers = $.ligerManagers || {};
    $.ligerManagers.Portal = function (options, po) {
        this.options = options;
        this.po = po;
    };

    $.ligerManagers.Portal.prototype={
        __getType: function () {
            return 'Portal';
        },
        __idPrev: function () {
            return 'Portal';
        },
        _extendMethods: function () {
            return $.ligerMethos.Portal;
        },
        _init: function () {
            var g = this, p = this.options;
            $.ligerui.controls.Portal.base._init.call(this);
            if ($(">div", g.element).length) //如果已经定义了DIV子元素,那么这些元素将会转换为columns,这里暂时保存到tempInitPanels
            {
                p.columns = [];
                $(">div", g.element).each(function (i, jpanel) {
                    p.columns[i] = {
                        panels: []
                    };
                });

                g.tempInitPanels = $("<div></div>");
                $(">div", g.element).appendTo(g.tempInitPanels);
            }
            if (!p.rows && p.columns) {
                p.rows = [{
                    columns: p.columns
                }];
            }
        },
        _render: function () {
            var g = this, p = this.options;

            g.portal = $(g.element).addClass("l-portal").html("");

            g.set(p);

        },
        _setRows: function (rows) {
            var g = this, p = this.options;
            g.rows = [];
            if (rows && rows.length) {
                for (var i = 0; i < rows.length; i++) {
                    var row = rows[i];
                    var jrow = $('<div class="l-row"></div>').appendTo(g.portal);
                    g.rows[i] = g._renderRow({
                        row: row,
                        rowIndex: i,
                        jrow: jrow
                    });
                    jrow.append('<div class="l-clear"></div>');
                }
            }
        },
        _renderRow: function (e) {
            var row = e.row, rowIndex = e.rowIndex, jrow = e.jrow;
            var g = this, p = this.options;
            var rowObj = {
                element: jrow[0]
            };
            if (row.width) jrow.width(row.width);
            if (row.height) jrow.height(row.height);
            if (row.columns) rowObj.columns = [];
            if (row.columns && row.columns.length) {
                for (var i = 0; i < row.columns.length; i++) {
                    var column = row.columns[i];
                    var jcolumn = $('<div class="l-column"></div>').appendTo(jrow);
                    rowObj.columns[i] = g._renderColumn({
                        column: column,
                        columnIndex: i,
                        jcolumn: jcolumn,
                        rowIndex: rowIndex
                    });
                }
            }
            return rowObj;
        },
        remove: function (e) {
            var g = this, p = this.options;
            var rowIndex = e.rowIndex, columnIndex = e.columnIndex, index = e.index;
            if (index == null) index = -1;
            if (index >= 0 && g.rows[rowIndex] && g.rows[rowIndex].columns && g.rows[rowIndex].columns[columnIndex] && g.rows[rowIndex].columns[columnIndex].panels) {
                var panel = g.rows[rowIndex].columns[columnIndex].panels[index];
                panel && panel.close();
                g._updatePortal();
            }
        },
        add: function (e) {
            var g = this, p = this.options;
            var rowIndex = e.rowIndex, columnIndex = e.columnIndex, index = e.index, panel = e.panel;
            if (index == null) index = -1;
            if (!(g.rows[rowIndex] && g.rows[rowIndex].columns && g.rows[rowIndex].columns[columnIndex])) return;
            var gColumn = g.rows[rowIndex].columns[columnIndex], pColumn = p.rows[rowIndex].columns[columnIndex], ligerPanel, jcolumn = $(gColumn.element);
            pColumn.panels = pColumn.panels || [];
            gColumn.panels = gColumn.panels || [];
            pColumn.panels.splice(index, 0, panel);
            if (index < 0) {
                var jpanel = $('<div></div>').insertBefore(gColumn.jplace);
                ligerPanel = jpanel.ligerPanel(panel);
            } else if (gColumn.panels[index]) {
                var jpanel = $('<div></div>').insertBefore(gColumn.panels[index].panel);
                ligerPanel = jpanel.ligerPanel(panel);
            }
            if (ligerPanel) {
                ligerPanel.bind('closed', g._createPanelClosed());
                g.setPanelEvent({
                    panel: ligerPanel
                });
                gColumn.panels.splice(index, 0, ligerPanel);
            }
            g._updatePortal();
        },
        _createPanelClosed: function () {
            var g = this, p = this.options;
            return function () {
                var panel = this;//ligerPanel对象
                var panels = g.getPanels();
                var rowIndex, columnIndex, index;
                $(panels).each(function () {
                    if (this.panel == panel) {
                        rowIndex = this.rowIndex;
                        columnIndex = this.columnIndex;
                        index = this.index;
                    }
                });
                p.rows[rowIndex].columns[columnIndex].panels.splice(index, 1);
                g.rows[rowIndex].columns[columnIndex].panels.splice(index, 1);
            };
        },
        _renderColumn: function (e) {
            var column = e.column, columnIndex = e.columnIndex, jcolumn = e.jcolumn;
            var rowIndex = e.rowIndex;
            var g = this, p = this.options;
            var columnObj = {
                element: jcolumn[0]
            };
            if (column.width) jcolumn.width(column.width);
            if (column.height) jcolumn.height(column.height);
            if (column.panels) columnObj.panels = [];
            if (column.panels && column.panels.length) {
                for (var i = 0; i < column.panels.length; i++) {
                    var panel = column.panels[i];
                    var jpanel = $('<div class="l-panel"></div>').appendTo(jcolumn);
                    columnObj.panels[i] = jpanel.ligerPanel(panel);
                    //columnObj.panels[i].bind('closed', g._createPanelClosed());
                    g.setPanelEvent({
                        panel: columnObj.panels[i]
                    });
                }
            } else if (g.tempInitPanels) {

                var tempPanel = g.tempInitPanels.find(">div:eq(" + columnIndex + ")");
                if (tempPanel.length) {
                    columnObj.panels = [];
                    var panelOptions = {};
                    var jelement = tempPanel.clone();
                    if (liger.inject && liger.inject.getOptions) {
                        panelOptions = liger.inject.getOptions({
                            jelement: jelement,
                            defaults: $.ligerDefaults.Panel,
                            config: liger.inject.config.Panel
                        });
                    }
                    columnObj.panels[0] = jelement.appendTo(jcolumn).ligerPanel(panelOptions);
                    columnObj.panels[0].bind('closed', g._createPanelClosed());
                    g.setPanelEvent({
                        panel: columnObj.panels[0]
                    });
                }
            }
            columnObj.jplace = $('<div class="l-column-place"></div>').appendTo(jcolumn);
            return columnObj;
        },
        setPanelEvent: function (e) {
            //panel:ligerui对象,jpanel:jQuery dom对象
            var panel = e.panel, jpanel = panel.panel;
            var g = this, p = this.options;
  
            //拖拽支持
            if ($.fn.ligerDrag && p.draggable) {
                jpanel.addClass("l-panel-draggable").ligerDrag({
                    proxy: false, revert: true,
                    handler: ".l-panel-header-drag",
                    onRendered: function () {
                    },
                    onStartDrag: function (current, e) {          //alert(JSON.stringify(jpanel));
                        g.portal.find(">.l-row").addClass("l-row-dragging");
                        this.jplace = $('<div class="l-panel-place"></div>');
                        this.jplace.height(jpanel.height());
                        jpanel.width(jpanel.width());
                        jpanel.addClass("l-panel-dragging");
                        jpanel.css("position", "absolute");
                        jpanel.after(this.jplace);
                        g._updatePortal();
                    },
                    onDrag: function (current, e) {
                        var pageX = e.pageX || e.screenX, pageY = e.pageY || e.screenY;
                        var height = jpanel.height(), width = jpanel.width(), offset = jpanel.offset();
                        var centerX = offset.left + width / 2, centerY = offset.top + 10;
                        var panels = g.getPanels(), emptyColumns = g.getEmptyColumns();
                        var result = getPositionIn(panels, emptyColumns, centerX, centerY);
                        if (result) {
                            //判断是否跟上次匹配的位置一致
                            if (this.placeStatus) {
                                if (this.placeStatus.panel && result.panel) {
                                    if (this.placeStatus.panel.rowIndex == result.panel.rowIndex &&
                                this.placeStatus.panel.columnIndex == result.panel.columnIndex &&
                                this.placeStatus.panel.index == result.panel.index &&
                                this.placeStatus.position == result.position) {
                                        return;
                                    }
                                }
                                if (this.placeStatus.column && result.column) //定位到空元素行
                                {
                                    if (this.placeStatus.column.rowIndex == result.column.rowIndex && this.placeStatus.column.columnIndex == result.column.columnIndex && this.placeStatus.position == result.position) {
                                        return;
                                    }
                                }
                            }
                            if (result.position == "top") {
                                this.jplace.insertBefore(result.panel ? result.panel.jpanel : result.column.jplace);
                                this.savedPosition = result.panel ? result.panel : result.column
                                this.savedPosition.inTop = true;
                            } else if (result.position == "bottom") {
                                this.jplace.insertAfter(result.panel.jpanel);
                                this.savedPosition = result.panel;
                                this.savedPosition.inTop = false;
                            }
                            this.placeStatus = result;
                        }
                        else//没有匹配到
                        {
                            this.placeStatus = null;
                        }

                        //从指定的元素集合匹配位置
                        function getPositionIn(panels, columns, x, y) {
                            for (i = 0, l = panels.length; i < l; i++) {
                                var o = panels[i];
                                if (o.panel == panel) //如果是本身
                                {
                                    continue;
                                }
                                var r = positionIn(o, null, x, y);
                                if (r) return r;
                            }
                            for (i = 0, l = columns.length; i < l; i++) {
                                var column = columns[i];
                                var r = positionIn(null, column, x, y);
                                if (r) return r;
                            }
                            return null;
                        }
                        //坐标在目标区域范围内 x,y为panel标题栏中间的位置
                        function positionIn(panel, column, x, y) {
                            var jelement = panel ? panel.jpanel : column.jplace;
                            if (!jelement) return null;
                            var height = jelement.height(), width = jelement.width();
                            var left = jelement.offset().left, top = jelement.offset().top;
                            var diff = 3;
                            if (x > left - diff && x < left + width + diff) {
                                if (y > top - diff && y < top + height / 2 + diff) {
                                    return {
                                        panel: panel,
                                        column: column,
                                        position: "top"
                                    };
                                }
                                if (y > top + height / 2 - diff && y < top + height + diff) {
                                    return {
                                        panel: panel,
                                        column: column,
                                        position: panel ? "bottom" : "top"
                                    };
                                }
                            }
                            return null;
                        }
                    },
                    onStopDrag: function (current, e) {
                        g.portal.find(">.l-row").removeClass("l-row-dragging");
                        //alert(JSON.stringify($(panel.panel).width()));
                        $(panel.panel).width(this.jplace.width());
                        jpanel.removeClass("l-panel-dragging");
                        //将jpanel替换到jplace的位置 
                        if (this.jplace) {
                            jpanel.css({
                                "position": "relative",
                                "left": null,
                                "top": null
                            });
                            jpanel.insertAfter(this.jplace);
                            g.portal.find(">.l-row > .l-column >.l-panel-place").remove();

                            if (this.savedPosition) {
                                var panels = g.getPanels();
                                var rowIndex, columnIndex, index;
                                $(panels).each(function () {
                                    if (this.panel == panel) {
                                        rowIndex = this.rowIndex;
                                        columnIndex = this.columnIndex;
                                        index = this.index;
                                    }
                                });
                                var oldPanelOptions = p.rows[rowIndex].columns[columnIndex].panels[index];
                                var oldPanel = g.rows[rowIndex].columns[columnIndex].panels[index];
                                p.rows[rowIndex].columns[columnIndex].panels.splice(index, 1);
                                g.rows[rowIndex].columns[columnIndex].panels.splice(index, 1);

                                if (this.savedPosition.panel) {

                                    p.rows[this.savedPosition.rowIndex].columns[this.savedPosition.columnIndex].panels.splice(this.savedPosition.index + this.savedPosition.inTop ? -1 : 0, 0, oldPanelOptions);
                                    g.rows[this.savedPosition.rowIndex].columns[this.savedPosition.columnIndex].panels.splice(this.savedPosition.index + this.savedPosition.inTop ? -1 : 0, 0, oldPanel);
                                } else {
                                    p.rows[this.savedPosition.rowIndex].columns[this.savedPosition.columnIndex].panels = [oldPanelOptions];
                                    g.rows[this.savedPosition.rowIndex].columns[this.savedPosition.columnIndex].panels = [oldPanel];
                                }
                            }
                        }
                        g._updatePortal();

                        return false;
                    }
                });
            }

        },
        _updatePortal: function () {
            var g = this, p = this.options;
            $(g.rows).each(function (rowIndex) {
                $(this.columns).each(function (columnIndex) {
                    if (this.panels && this.panels.length) {
                        $(this.element).removeClass("l-column-empty");
                    } else {
                        $(this.element).addClass("l-column-empty");
                    }
                    
                });
            });
        },
        getPanels: function () {
            var g = this, p = this.options;
            var panels = [];
            $(g.rows).each(function (rowIndex) {
                $(this.columns).each(function (columnIndex) {
                    $(this.panels).each(function (index) {
                        panels.push({
                            rowIndex: rowIndex,
                            columnIndex: columnIndex,
                            index: index,
                            panel: this,
                            jpanel: this.panel
                        });
                    });
                });
            });
            return panels;
        },
        getPanel: function (e) {
            var g = this, p = this.options;
            e = $.extend({
                rowIndex: 0,
                columnIndex: 0,
                index: 0
            }, e);
            var panel = null;
            $(g.rows).each(function (rowIndex) {
                $(this.columns).each(function (columnIndex) {
                    $(this.panels).each(function (index) {
                        if (panel) return;
                        if (rowIndex == e.rowIndex && columnIndex == e.columnIndex && index == e.index) {
                            panel = this;
                        }
                    });
                });
            });
            return panel;
        },
        getEmptyColumns: function () {
            var g = this, p = this.options;
            var columns = [];
            $(g.rows).each(function (rowIndex) {
                $(this.columns).each(function (columnIndex) {
                    if (!this.panels || !this.panels.length) {
                        columns.push({
                            rowIndex: rowIndex,
                            columnIndex: columnIndex,
                            jplace: this.jplace
                        });
                    }
                });
            });
            return columns;
        },
        _setUrl: function (url) {
            var g = this, p = this.options;
            if (!url) return;
            $.ajax({
                url: url, data: p.parms, type: p.method, dataType: 'json',
                success: function (rows) {
                    g.set('rows', rows);
                }
            });
        },
        _setWidth: function (value) {
            value && this.portal.width(value);
        },
        collapseAll: function () {
            var g = this, p = this.options;
            var panels = g.getPanels();
            $(panels).each(function (i, o) {
                var panel = o.panel;
                panel.collapse();
            });
        },
        expandAll: function () {
            var g = this, p = this.options;
            var panels = g.getPanels();
            $(panels).each(function (i, o) {
                var panel = o.panel;
                panel.expand();
            });
        }
    };

    $.fn.ligerPortal = function (p) {
        this.each(function () {
            p = $.extend({}, $.ligerDefaults.Panel, p || {});
            var po = {};
            var g = new $.ligerManagers.Portal(p, po);

            g.portal = $(this).addClass("l-portal").html("");
            if ($(">div", g.element).length) //如果已经定义了DIV子元素,那么这些元素将会转换为columns,这里暂时保存到tempInitPanels
            {
                p.columns = [];
                $(">div", g.element).each(function (i, jpanel) {
                    p.columns[i] = {
                        panels: []
                    };
                });

                g.tempInitPanels = $("<div></div>");
                $(">div", g.element).appendTo(g.tempInitPanels);
            }
            if (!p.rows && p.columns) {
                p.rows = [{
                    columns: p.columns
                }];
            }

            g._setRows(p.rows);

            $.ligerui.addManager(this, g);
        })
        return $.ligerui.getManager(this);
    }
})(jQuery);