/* 
    Base window class 
    DO NOT CALL IT DIRECTLY!
*/

__Window = _class({

    members: {
    
        id: null,
        app: null,
        param: null,
        extwin: null,
        name: null,

        title: null,
        currentTemplate: null,

        preserveBoxParams: null,
        
        // generated id's resgistry for the window's extjs components
        componentIds: null,
        components: null,
        
        onclose: null,
        onrefresh: null
    },

    constructor: function(app) {

        this.app = app;
        this.id = 'win_' + random();
        this.param = {
            xmldata: {}
        };
        this.preserveBoxParams = false;
    },

    methods: {
    
    	// virtual
    	processBroadcast: function(data) {},
    
        genId : function(compName) {
        
            this.componentIds[compName] = 'component' + random() + random() + random();
            return this.componentIds[compName];
        },

        loadContent : function(template, request, callback) {
        
            application.startLoad();
            if(this.extwin != null) {
                this.extwin.removeAll(true);
                this.extwin.add({
                    xtype: 'container',
                    style: 'width:100%;height:100%;background-color:#dCe9f8;background-image:url(library/client/ext-3.0.0/resources/images/default/shared/blue-loading.gif);background-repeat:no-repeat;background-position:center;'
                });
                this.extwin.doLayout();
            }

            this.currentTemplate = template;
            
            if(request != null) {
                this.param.xmldata.query = request.packet.query;
                this.param.xmldata.xmldata = request.packet.xmldata;
                var req = new JSON.Request( function(response) {
                    this.response = response;
                    var data = new JSON.Document('xmldata', response.packet.xmldata);
                    response.packet.type == "response"
                        ? this.__setTemplate(template, data, callback)
                        : this.__setTemplate('error.js', data)
                        ;
                }.bind(this));
                req.send(this.app.server, request);
            } else this.__setTemplate(template, null, callback);
        },
        
        setContent : function(template, xmldata, callback) {
            !xmldata ? xmldata = new JSON.Document('xmldata',{} ) : '';
            this.__setTemplate(template, xmldata, callback)
        },
        
        __setTemplate : function(template, xmldata, callback) {

            this.componentIds = {};

            var tplName;
            var tplPath;
            for(var i in template) {
                tplName = i;
                tplPath = template[tplName];
                break;
            }
            
            if(_defined(core.jstemplates[tplName])) {
            
                var tpl = core.jstemplates[tplName].fill(this, xmldata);
                this.gatherParams(tpl.tpl);

                if(!this.extwin) this.createWindow();
                else {
                    this.extwin.removeAll(true);
                    this.updateWindowParams();
                }
                
                this.extwin.el.dom.removeAttribute('title');

                // add everything and draw
                this.extwin.add(tpl.tpl.items);
                this.extwin.doLayout();
                //if(tpl.layout) this.extwin.setLayout(tpl.layout);
                
                this.registerComponents();
                
                // the template callback function, it handles what "wouldn't fit"/"might not be clear" in the config
                //tpl.handler(this, xmldata);
                for(var i = 0, length = tpl.handler.length; i < length; i++) tpl.handler[i](this, xmldata);

                // the other callback
                if(callback) callback(xmldata);
                
                this.preserveBoxParams = false;
                application.stopLoad();
            } else {

                var script = document.createElement('script');
                script.setAttribute('type', 'text/javascript');
                var scriptPath = '';
                var slashIndex = tplPath.indexOf('/');
                if(slashIndex == -1) scriptPath = 'templates/' + tplPath;
                else scriptPath = 'modules/' + tplPath.substr(0, slashIndex) + '/client/templates/' + tplPath.substr(slashIndex + 1);
                script.setAttribute('src', scriptPath + '?r=' + (random()).toString());
                
                if(msie()) {
                    script.obj = this;
                    script.onreadystatechange = function () {
      			        if (this.readyState == 'complete' || this.readyState == 'loaded') {
                            if(err_count > this.registered_err_count) return;
                            core.scriptNodes[tplName] = this;
                            this.obj.__setTemplate(template, xmldata, callback);
      			        }
					};
                } else {
                    script.onload = function(s) {
                        // break the nasty error loop
                        if(err_count > s.target.registered_err_count) return;
                        core.scriptNodes[tplName] = script;
                        this.__setTemplate(template, xmldata, callback);
                    }.bind(this);
                }

                script.registered_err_count = err_count;
                document.body.appendChild(script);
            }
        },
        
        registerComponents: function() {
        
            this.components = {};
            for(var i in this.componentIds) this.components[i] = Ext.getCmp(this.componentIds[i]);
        },

        setTitle: function(title) {

            this.extwin.setTitle(title);
        },

        refresh : function(preserveBoxParams) {
        
            if(this.onrefresh) this.onrefresh();

            this.preserveBoxParams = typeof(preserveBoxParams) == 'undefined' ? true : preserveBoxParams;
            
            if(_defined(this.param.xmldata.query)) {
                var xml = new JSON.Document('packet', {});
                xml.packet.query = this.param.xmldata.query;
                xml.packet.type = "request";
                xml.packet.xmldata = this.param.xmldata.xmldata;
                this.loadContent(this.currentTemplate, xml, null);
            } else this.loadContent(this.currentTemplate, null, null);
        },

        unloadTemplate: function() {
        
            // first re-link the base templates, this is mostly usefull in the development phase
            relinkScriptById('tpl_macros');
            relinkScriptById('tpl_base');
        
            var tplName;
            var tplPath;
            for(var i in this.currentTemplate) {
                tplName = i;
                tplPath = this.currentTemplate[tplName];
                break;
            }

            if(_defined(core.scriptNodes[tplName])) {
                var script = core.scriptNodes[tplName];
                script.parentNode.removeChild(script);
                delete core.scriptNodes[tplName];
                delete core.jstemplates[tplName];
            }
        }
    }
});

/* 
    Block class
    Inherited from __Window
*/

Block = _class({

    inherits: [

        __Window
    ],
    
    members: {

        //...
    },

    constructor: function(app, name) {

        var existing = application.getWindowByName(name);
        if(!existing) {
            this.__parent.__construct(app);
            this.name = name;
        } else {
            existing.preserveBoxParams = true;
            existing.__attachTo(this);
        }
    },

    destructor: function() {

       this.extwin.ownerCt.remove(this.extwin, true);

        if(this.timer)clearInterval(this.timer);
        
        for(var i = 0; i < this.app.docking.length; i++) {
            if(this.app.docking[i].id == this.id) {
                this.app.docking.splice(i, 1);
                break;
            }
        }
    },

    methods: {
    
        updateWindowParams: function() {

            this.setTitle(this.title);
            if(!this.preserveBoxParams) {
                this.resize(400);
            }
        },
        
        resize: function(height) {
        
            this.extwin.resizable.resizeTo(this.extwin.getWidth(), height);
        },
    
        gatherParams: function(tpl) {

            this.title = tpl.title ? tpl.title : null;
        },
        
        createWindow: function() {
        
            switch(null) {
                case this.title:    alert('missing required config option \'title\'');  break;
            }
        
            var tools = [{
                id:'refresh',
                qtip: 'Refresh window',
                handler: function() {
                    this.unloadTemplate();
                    this.refresh(false);
                },
                scope: this
            },/*{
                id: 'refresh',
                qtip: 'Refresh',
                handler: function() {
                    this.refresh();
                },
                scope: this
            },*/{
                id:'close',
                qtip: 'Close',
                handler: function(e, target, panel) {
                    this.close();
                },
                scope: this
            }];
            
            
            //this is related to the state management
            /*
            Ext.ns('blockPortlet');
            blockPortlet.statefulBlock = Ext.extend(Ext.ux.Portlet, {
                stateEvents: ['resize'],
                getState: function(){
                    return {
                        height: this.height
                    }
                },
                applyState: function(state){
                    //console.log(this);
                    alert(state.height);
                }
            });
            */
            
            this.extwin = new Ext.ux.Portlet({
                id: this.id,
                title: this.title,
                layout: 'anchor',
                height: 400,
                plain: true,
                // quick fix
                bodyStyle: "background-color:#CCD9E8",
                tools: tools
            });

            var portal = Ext.getCmp('portal');
            
            var heights = [];
            // look into each column, from left to right
            for(var i = 0; i < portal.items.getCount(); i++) {
                var column = portal.items.itemAt(i);
                // gather the column's items' total height
                heights.push(0);
                for(var j = 0; j < column.items.getCount(); j++) {
                    heights[i] += column.items.itemAt(j).getOuterSize().height;
                }
            }
            var insertAt = 0;
            var minHeight = heights[0];
            for(var i = 0; i < portal.items.getCount(); i++) {
                if(heights[i] < minHeight) {
                    minHeight = heights[i];
                    insertAt = i;
                }
            }
            portal.items.itemAt(insertAt).add(this.extwin);
            portal.items.itemAt(insertAt).doLayout();
            
            this.extwin.resizable = new Ext.Resizable(this.extwin.el.dom, {
                handles: 's',
                height: 400,
                transparent: true,
                listeners: {
                    // this listener links the resizable to the panel
                    resize: function(resizable, width, height, event) {
                        this.setHeight(height);
                    }.bind(this.extwin)
                }
            });

            this.__attachTo($(this.id));

            this.app.docking.push(this);
        },

        close : function() {

            if(this.onclose) this.onclose();
            this.__destroy();
        },
        
        autorefresh : function() {
        
            if(this.app.editMode==0) return;
            if(this.timer) {
                if(this.interval != this.param.xmldata.options.autorefresh) {
                    clearInterval(this.timer);
                    this.interval = this.param.xmldata.options.autorefresh;
                    this.timer = setInterval(this.autorefresh.bind(this), this.param.xmldata.options.autorefresh * 60000);
                } else this.refresh();
            } else {
                this.interval = this.param.xmldata.options.autorefresh;
                this.timer = setInterval(this.autorefresh.bind(this), this.param.xmldata.options.autorefresh * 60000);
            }
        }
    }
});

/* 
    Window class
    Inherited from __Window
*/

Window = _class({

    inherits: [

        __Window
    ],
    
    members: {
    
        width: null,
        height: null,
        pos: null,
        modal: false,
        minimized: null,
        maximized: null,
        active: null
    },
    
    constructor: function(app, name) {

        //this.modal = false;
        this.minimized = false;
        this.maximized = false;
        this.active = true;

        var existing = application.getWindowByName(name);
        if(!existing) {
            this.__parent.__construct(app);
            this.name = name;
        } else {
            if(existing.minimized) existing.unminimize();
            else existing.moveOnTop();
            existing.preserveBoxParams = true;
            existing.__attachTo(this);
        }
    },

    destructor: function() {

        Ext.getCmp('taskbar').remove(this.taskbar_button, true);
        Ext.getCmp('taskbar').doLayout();
        if(Ext.isIE7) this.extwin.hide();
        else this.extwin.destroy();

        for(var i = 0; i < this.app.windows.length; i++) {
            if(this.app.windows[i].id == this.id) {
                this.app.windows.splice(i, 1);
                break;
            }
        }
    },

    methods: {
    
        maximize: function() {
        
            if(!this.maximized) {
                this.maximized = true;
                this.extwin.maximize();
                this.extwin.getTool('maximize').hide();
                this.extwin.getTool('restore').show();
            }
        },
        
        restore: function() {
        
            if(this.maximized) {
                this.maximized = false;
                this.extwin.restore();
                this.extwin.getTool('restore').hide();
                this.extwin.getTool('maximize').show();
            }
        },

        minimize: function() {
        
            if(!this.minimized) {
                this.minimized = true;
                this.extwin.hide();
                this.taskbar_button.toggle(false);
            }
        },

        unminimize: function() {

            if(this.minimized) {
                this.minimized = false;
                this.extwin.show();
                this.moveOnTop();
            }
        },

        taskbarClick: function() {
        
            if(this.minimized) this.unminimize();
            else if(!this.active) this.moveOnTop();
            else this.minimize();
        },

        createWindow: function() {
        
            switch(null) {
                case this.title:    alert('missing required config option \'title\'');  break;
                case this.width:    alert('missing required config option \'width\'');  break;
                case this.height:   alert('missing required config option \'height\''); break;
            }
        
            var tools = [{
                id:'refresh',
                qtip: 'Refresh window',
                handler: function() {
                    this.unloadTemplate();
                    this.refresh(false);
                },
                scope: this
            },{
                id: 'minimize',
                qtip: 'Minimize window',
                handler: function() {
                    this.minimize();
                },
                scope: this
            },{
                id: 'maximize',
				hidden: this.maximized,
                qtip: 'Maximize window',
                handler: function() {
                    this.maximize();
                },
                scope: this
            },{
                id: 'restore',
                hidden: !this.maximized,
                qtip: 'Restore window to normal size',
                handler: function() {
                    this.restore();
                },
                scope: this
            },/*,{
                id: 'refresh',
                qtip: 'Refresh',
                handler: function() {
                    this.refresh();
                },
                scope: this
            }*/{
                id:'close',
                qtip: 'Close',
                handler: function(e, target, panel) {
                    this.close();
                },
                scope: this
            }];
            
            this.taskbar_button = new Ext.Button({
                //tooltip: this.title,
                text: this.title,
                width: 75,
                handler: function() {
                    this.taskbarClick();
                }.bind(this),
                enableToggle: true,
                pressed: true
            });

            this.extwin = new Ext.Window({
				//maximized: this.maximized,
                id: this.id,
                title: this.title,
                layout:'anchor',
                width: this.width,
                height: this.height,
                modal: this.modal,
                constrain: true,
                plain: true,
                tools: tools,
                listeners: {
                    activate: function() {
                        application.setWindowActive(this);
                        application.toggleTaskbarButton(this.taskbar_button, true);
                    }.bind(this),
                    titlechange: function(panel, title) {
                        this.taskbar_button.setText(title);
                        //this.taskbar_button.setTooltip(title);
                    }.bind(this)
                },
                renderTo: Ext.getCmp('portal').getEl().dom
            });
			
            this.extwin.show();

            Ext.getCmp('taskbar').add(this.taskbar_button);
            Ext.getCmp('taskbar').doLayout();
            
            if(this.pos != null) this.move(this.pos);
			
			if(this.maximized) {
				this.maximized = false;
				this.maximize();
			}
			
            this.__attachTo($(this.id));

            this.app.windows.push(this);
        },
    
        updateWindowParams: function() {

            this.setTitle(this.title);
            if(!this.maximized && !this.preserveBoxParams) {
                this.resize(this.width, this.height);
                this.move(this.pos);
            }
        },
    
        gatherParams: function(tpl) {

			this.maximized = _defined(tpl.maximized) ? tpl.maximized : false;
            this.title = tpl.title ? tpl.title : null;
            this.width = tpl.width ? tpl.width : null;
            this.height = tpl.height ? tpl.height : null;
            this.pos = tpl.pos ? tpl.pos : null;
            this.modal = tpl.modal ? tpl.modal : false;
        },

        close : function() {

            if(this.onclose) this.onclose();
            this.__destroy();
        },
        
        cancel : function(id) {

            var name = this.getElementsByTagName('form')[0].id;
            var a = new XML.Document('xmldata',{});
            a.xmldata = this.app.parseForm($(name)).form;
            if(this.app.compareState(name+id,a.serialize())) this.close();
            else return;
        },
        
        setOverlay : function() {

            var overlay = _('div');
            var height = 0;
            overlay.id = this.id + '_overlay';
            overlay.className = 'overlay';
            //overlay.style.zIndex = parseInt(this.style.zIndex) - 1 + "px";
            var height = (document.documentElement.clientHeight > document.body.clientHeight) ?  document.documentElement.clientHeight : document.body.clientHeight;
            overlay.style.height = height +  "px";
            document.body.appendChild(overlay);
            return overlay;
        },
        
        moveOnTop : function() {

            this.extwin.toFront();
        },
        
        center : function() {
    
            this.extwin.center();
        },
        
        topWindow : function() {

            var level = 100;
            var win = null;
            for( var i in this.app.windows) {
                if(this.app.windows[i] != this && parseInt(this.app.windows[i].style.zIndex) > level) {
                    level = parseInt(this.app.windows[i].style.zIndex);
                    win = this.app.windows[i];
                }
            }
    
            return win;
        },
        
        resize: function(width, height) {
        
        	this.width = width;
        	this.height = height;
            this.extwin.setSize(width, height);
        },
        
        move: function(pos) {
        
            if(pos == null || pos == '') return;

            var extwin = this.extwin;
            var currSize = extwin.getSize();
            var currPos = extwin.getPosition();
            // WTH do they return size and pos in a different format?
            currPos = {x: currPos[0], y: currPos[1]};
            var workspace = Ext.getCmp('portal').getBox();

            var x = currPos.x;
            var y = currPos.y;
            pos = pos.split(' ');

            if(pos[0] != '') {
                if(pos[0] == 'center') x = workspace.x + workspace.width / 2 - currSize.width / 2;
                else if(pos[0].substr(pos[0].length - 1) == '%') {
                    pos[0] = pos[0].substr(0, pos[0].length - 1);
                    if(pos[0].isNumber()) x = Math.round(workspace.x + workspace.width * (pos[0] / 100));
                } else if(pos[0].isNumber()) x = parseInt(pos[0]) + workspace.x;
            }
            
            if(pos.length > 1) {
                if(pos[1] == 'center') y = workspace.y + workspace.height / 2 - currSize.height / 2;
                else if(pos[1].substr(pos[1].length - 1) == '%') {
                    pos[1] = pos[1].substr(0, pos[1].length - 1);
                    if(pos[1].isNumber()) Math.round(y = workspace.y + workspace.height * (pos[1] / 100));
                } else if(pos[1].isNumber()) y = parseInt(pos[1]) + workspace.y;
            }
            
            extwin.setPosition(x, y);
        }
    }
});

function getByID(obj,id) {

    for(var i=0;i<obj.childNodes.length;i++) {
        if(obj.childNodes[i].id && obj.childNodes[i].id == id) return obj.childNodes[i];
        if(obj.childNodes[i].childNodes.length && obj.childNodes[i].childNodes.length > 0 ) return getByID(obj.childNodes[i],id);
    }
}

/*
function uploadBox(app, data, callback) {
    var conf = new XML.Document('xmldata', {});
    conf.xmldata.options = {title:'Upload File', modale:"1", name:"uploadBox"};
    conf.xmldata.style = {width:'300px', height:'120px', position: 'absolute', left:'300px', top:'200px'};
    conf.xmldata.button = [{image:'close.gif', action:'close'}];
    var doc = new XML.Document('xmldata', {'var':data});
    var win = new Window(app, conf);
    win.setContent('upload.xsl', doc);
    win.callback = callback;
}
*/
