/* send debug output to firebug console */
function debug(str) {
    if (window.console != undefined) {
        console.debug(str);
    }
}

/* uppercase first char */
function ucfirst(str) {
    var firstLetter = str.slice(0,1);
    return firstLetter.toUpperCase() + str.substring(1);
}

/* global Thruk Panorama Object */
Ext.namespace("TP");
var TP = {
    snap_x: 20,
    snap_y: 20,
    offset_y: 25,

    get_snap: function (x, y) {
        newx = Math.round(x/TP.snap_x) * TP.snap_x;
        newy = Math.round(y/TP.snap_y) * TP.snap_y + 5;
        if(newy < TP.offset_y) { newy = TP.offset_y; }
        return([newx, newy]);
    },

    add_pantab: function(id) {
        var tabpan = Ext.getCmp('tabpan');
        var size   = tabpan.items.length;
        var nextid = this.getNextId("tabpan-tab", id);

        /* add new tab panel */
        tabpan.add(new TP.Pantab({id: nextid})).show();

        /* move new-tab button at the end */
        tabpan.getTabBar().move(size-1, size);

        /* make tab title editable */
        var tabhead = tabpan.getTabBar().items.getAt(size-1);
        if(tabhead.rendered == false) {
            tabhead.addListener('afterrender', function(This, eOpts) {
                TP.addDblClickRename(This.getEl(), tabhead, nextid);
            });
        } else {
            TP.addDblClickRename(tabhead.getEl(), tabhead, nextid);
        }

        /* save tabs state */
        Ext.getCmp('tabpan').saveState();

        /* return false to prevent newtab button being activated */
        return false;
    },

    /* add given panlet */
    add_panlet: function(config, smartPlacement) {
        if(config.conf == undefined) {
            config.conf = {};
        }
        config.conf.id = this.getNextId("panlet", config.id);
        var state = cp.readValues();
        if(state[config.conf.id] != undefined
           && state[config.conf.id].xdata != undefined
           && state[config.conf.id].xdata.cls != undefined) {
            config.type = state[config.conf.id].xdata.cls;
        }
        if(config.type == undefined) {
            throw("add_panlet(): no type!");
        }
        var pan = Ext.getCmp('tabpan');
        var tb  = pan.getActiveTab();
        if(!tb) {
            tb = pan.setActiveTab(0);
        }
        if(!tb) {
            throw("add_panlet(): no active tab!");
        }
        var win = Ext.create(config.type, config.conf);
        win.panel_id = tb.id;
        if(smartPlacement == undefined || smartPlacement == true) {
            pan.setActiveTab(tb); /* other wise panel won't be rendered and panel size is 0 */
            TP.fitWindowPlacement(tb, win);
        }
        if(!config.skip_state) {
            tb.window_ids.push(win.id);
            tb.saveState();
        }
        return true;
    },

    /* return next unused id */
    getNextId: function(prefix, id) {
        if(id != undefined) {
            return id;
        }
        var nr = 1;
        while(Ext.getCmp(prefix + "_" + nr) != undefined) {
            nr++;
        }
        return(prefix + "_" + nr);
    },

    /* remove item from an array */
    removeFromList: function(list, item) {
        var newlist = [];
        for(var key in list) {
            if(list[key] != item) {
                newlist.push(list[key]);
            }
        }
        return(newlist);
    },

    /* show about window */
    aboutWindow: function() {
        new Ext.window.Window({
            autoShow:   true,
            modal:      true,
            title:      'About Thruks Panorama',
            buttonAlign: 'center',
            items: [{
                html: 'Thruk Panorama<br><br>Copyright 2012 Sven Nierlein, sven@consol.de<br>License: GPL v3<br>Version: [% version %][% IF branch %]~[% branch %][% END %][% IF c.config.omd_version %] <font size="-3">(OMD [% c.config.omd_version %])<\/font>[% END %]'
            }],
            fbar: [{
                text:'OK',
                handler: function() { this.up('window').destroy() }
            }]
        });
    },

    /* get box coordinates for given object */
    getBox: function(obj) {
        var pos  = obj.getPosition();
        var size = obj.getSize();
        var box = {
            tl: { x:pos[0], y:pos[1] },
            tr: { x:pos[0]+size.width, y:pos[1] },
            bl: { x:pos[0], y:pos[1]+size.height },
            br: { x:pos[0]+size.width, y:pos[1]+size.height }
        };
        return box;
    },

    /* smart placement for new windows */
    fitWindowPlacement: function(tab, win) {
        var box     = TP.getBox(win);
        var tabsize = tab.getSize();

        /* get list of boxes */
        var boxes = [];
        var tabpan = Ext.getCmp('tabpan');
        tabpan.items.each(function(panel) {
            if(panel.window_ids) {
                for(var nr in panel.window_ids) {
                    var id = panel.window_ids[nr];
                    var w  = Ext.getCmp(id);
                    if(id != win.id && (panel.id == win.panel_id || w.xdata.pinned == true )) {
                        boxes.push(TP.getBox(w));
                    }
                };
            }
        });

        /* get first place which fits */
        var x = 0;
        var y = TP.offset_y;
        while(TP.boxesOverlap(x, y, box, boxes)) {
            x = x + TP.snap_x;
            if(x+box.tr.x > tabsize.width) {
                x = 0;
                y = y + TP.snap_y;
            }
            if(y+box.bl.y > tabsize.height) {
                /* nothing matched, just placed at 0,0 */
                x = 0;
                y = TP.offset_y;
                break;
            }
        }
        win.setPosition(x, y);
    },
    /* returns true if any box ovelap */
    boxesOverlap: function(x, y, box, boxes) {
        var tmp_box = {
            tl: { x:x, y:y },
            tr: { x:x+(box.tr.x-box.tl.x), y:y },
            bl: { x:x, y:y+(box.br.y-box.tr.y) },
            br: { x:x+(box.tr.x-box.tl.x), y:y+(box.br.y-box.tr.y) }
        };

        for(var nr in boxes) {
            var b = boxes[nr];
            /* check if these boxes overlap */
            if(TP.boxOverlap(tmp_box, b)) { return true; }
            if(TP.boxOverlap(b, tmp_box)) { return true; }
        }
        return false;
    },
    /* returns true if both boxes ovelap */
    boxOverlap: function(b1, b2) {
        if(b1.tl.x >= b2.tl.x && b1.tl.x < b2.tr.x && b1.tl.y >= b2.tl.y && b1.tl.y <  b2.bl.y) { return true; }
        if(b1.tr.x >  b2.tl.x && b1.tr.x < b2.tr.x && b1.tr.y >= b2.tl.y && b1.tr.y <  b2.bl.y) { return true; }
        if(b1.bl.x >= b2.tl.x && b1.bl.x < b2.tr.x && b1.bl.y >  b2.tl.y && b1.bl.y <= b2.bl.y) { return true; }
        if(b1.br.x >  b2.tl.x && b1.br.x < b2.tr.x && b1.br.y >  b2.tl.y && b1.br.y <= b2.bl.y) { return true; }
        return false;
    },
    /* hide element in given form */
    hideFormElements: function(form, list) {
        form.getFields().each(function(f, i) {
            for(var nr in list) {
                if(f.name == list[nr]) { f.hide() }
            }
        });
    },
    /* refresh all site specific panlets */
    refreshAllSitePanel: function() {
        var panels = TP.getAllPanel();
        for(var nr in panels) {
            var p = panels[nr];
            if(p.reloadOnSiteChanges != undefined && p.reloadOnSiteChanges == true) {
                p.refreshHandler();
            }
        }
    },
    /* return all panlets */
    getAllPanel: function() {
        var panels = [];
        var tabpan = Ext.getCmp('tabpan');
        tabpan.items.each(function(panel) {
            if(panel.window_ids) {
                for(var nr in panel.window_ids) {
                    var id = panel.window_ids[nr];
                    var p  = Ext.getCmp(id);
                    panels.push(p);
                }
            }
        });
        return panels;
    },
    /* set form values from data hash */
    applyFormValues: function(form, data) {
        var fields = form.getFields();
        TP.setRefreshText(data, 'refresh', 'refresh_txt');
        fields.each(function(f) {
            var v = data[f.getName()];
            if(f.xtype == 'combobox' && f.multiSelect == true) {
                f.originalValue = v;
                f.value = v;
                f.setValue(v);
            }
            else if(f.inputType == 'checkbox') {
                f.setValue(v);
                f.originalValue = v;
            } else {
                f.originalValue = [ v ];
                f.setValue(v);
                f.value = v;
            }
        });

        /* checkbox groups are different */
        var items = form.getFields().items;
        for(var i in items) {
            var f = items[i];
            if(f.xtype == 'checkboxgroup') {
                f.removeAll();
                for(var x in initial_backends) {
                    var checked = false;
                    if(Ext.Array.contains(data.backends, x)) { checked = true; }
                    f.add({ boxLabel: initial_backends[x].name, name: 'backends', inputValue: x, checked: checked });
                }
            }
        };

        delete data['refresh_txt'];
        return true;
    },
    /* store form result in data hash  */
    storeFormToData: function(form, data) {
        var values = form.getFieldValues();
        /* save values to xdata store */
        for(var key in values) {
            data[key] = values[key];
        };
        /* checkboxgroups are different */
        var items = form.getFields().items;
        for(var i in items) {
            var f = items[i];
            if(f.xtype == 'checkboxgroup') {
                var result = {};
                var checked = f.getChecked();
                for(var nr in checked) {
                    c = checked[nr];
                    if(result[c.name] == undefined) {
                        result[c.name] = [];
                    }
                    result[c.name].push(c.inputValue);
                }
                for(var nr in result) {
                    data[nr] = result[nr];
                }
            }
        }
        return data;
    },
    /* clone an object */
    clone: function(o) {
        return(Ext.JSON.decode(Ext.JSON.encode(o)));
    },
    /* convert backends into array usable by data store */
    getBackendsArray: function(backends) {
        var data = [];
        for(var key in backends) {
            data.push([key, backends[key].name]);
        }
        return data;
    },
    /* default refresh handler */
    defaultSiteRefreshHandler: function(panel) {
        if(panel.xdata.url != '') {
            var url = panel.xdata.url;
            if(panel.loader.baseParams == undefined) {
                panel.loader.baseParams = {};
            }
            var baseParams = Ext.merge(panel.loader.baseParams, panel.xdata);
            delete baseParams['gridstate']; // not needed
            panel.loader.load({url:url, baseParams: baseParams});
        }
    },
    /* convert time frame into seconds */
    timeframe2seconds: function(timedef) {
        var res  = timedef.match(/^(\d+)(\w{1})/);
        if(res.length == 1) {
            return 3600;
        }
        var nr    = res[1];
        var unit  = res[2];
        if(unit == 'm') { return nr * 60; }     // minutes
        if(unit == 'h') { return nr * 3600; }   // hours
        if(unit == 'd') { return nr * 86400; }  // days
        if(unit == 'w') { return nr * 604800; } // weeks
        return 3600;
    },
    /* import tabs from string */
    importAllTabs: function(data) {
        try {
            data = cp.decodeValue(decode64(data));
        }
        catch(e) {
            Ext.MessageBox.alert('Failed', 'Import Failed!');
            return;
        }
        if(data == undefined || data == '') { data = {} }

        cp.clearAll();
        cp.loadData(data);
        Ext.getCmp('viewport').add(new TP.TabBar());
        window.setTimeout("window.location.reload()", 1000);
    },
    /* eval response data */
    getResponse: function(panlet, response) {
        var refresh = {setType: Ext.emptyFn };
        if(panlet != undefined) {
            refresh = panlet.getTool('refresh') || panlet.getTool('broken');
        }
        if(response.status == 200) {
            var data;
            try {
                data = eval("("+response.responseText+")");
            } catch(e) {
                if(refresh.setType) { refresh.setType('broken') }
                debug(e);
                return data;
            }
            if(refresh.setType) { refresh.setType('refresh') }
            /* extract pi details */
            if(data.pi_detail != undefined) {
                for(var key in data.pi_detail) {
                    initial_backends[key].state         = data.pi_detail[key].state;
                    initial_backends[key].program_start = data.pi_detail[key].program_start;
                }
            }
            /* contains a message? */
            var msg = Ext.util.Cookies.get('thruk_message');
            if(msg) {
                TP.Msg.msg(msg);
                // clear message
                var now = new Date();
                var expires = new Date(now.getTime() - (10*365*86400*1000)); // let the cookie expire 10 year ago
                Ext.util.Cookies.set('thruk_message', null, expires);
            }
            if(data.errors) {
                for(var nr in data.errors) {
                    TP.Msg.msg("fail_message~~"+data.errors[nr].message);
                }
            }
            return data;
        }
        debug("ERROR: " + response.status);
        debug(response);
        if(refresh.setType) { refresh.setType('broken') }
        return false;
    },
    /* sets text for refresh slider */
    setRefreshText: function(data, slider, text) {
        data[text] = TP.sliderValue2Txt(data[slider]);
    },
    /* convert value to human text */
    sliderValue2Txt: function(v) {
        if(v == -1) { return 'default'; }
        if(v ==  0) { return 'off'; }
        return v+'s';
    },
    /* start tab rotation interval */
    startRotatingTabs: function() {
        var tabpan = Ext.getCmp('tabpan');
        window.clearInterval(tabpan.interval_rotatetabs);
        if(tabpan.xdata.rotate_tabs > 0) {
            debug("starting tab rotation every " + tabpan.xdata.rotate_tabs + "seconds");
            tabpan.interval_rotatetabs = window.setInterval(TP.rotateTabs, tabpan.xdata.rotate_tabs * 1000);
        }
    },
    /* start server time */
    startServerTime: function() {
        var tabpan = Ext.getCmp('tabpan');
        window.clearInterval(tabpan.interval_servertime);
        var label = Ext.getCmp('server_time');
        if(!tabpan.xdata.server_time) {
            label.hide();
            return;
        }
        label.show();
        tabpan.interval_servertime = window.setInterval(TP.updateServerTime, 1000);
    },
    /* update server time */
    updateServerTime: function() {
        var label  = Ext.getCmp('server_time');
        var client = new Date();
        var time   = Math.floor((client.getTime() - delta_time) / 1000);
        var date   = TP.date_format(time, 'H:i');
        label.update(date);
    },
    /* stop tab rotation interval */
    stopRotatingTabs: function() {
        var tabpan = Ext.getCmp('tabpan');
        window.clearInterval(tabpan.interval);
    },
    /* rotate tabs once */
    rotateTabs: function() {
        var tabpan = Ext.getCmp('tabpan');
        var state  = tabpan.getState();
        var at     = state.activeTab+1;
        if(!tabpan.setActiveTab(at)) {
            tabpan.setActiveTab(1);
        }
    },
    addDblClickRename: function(el, item, id) {
        el.on("dblclick", function() {
            Ext.Msg.prompt('Change Title', '', function(btn, text) {
                if(btn == 'ok') {
                    Ext.getCmp(id).setTitle(text);
                }
            }, undefined, undefined, item.getText());
        });
    },
    /* sum list elements */
    arraySum: function(list) {
        var l=list.length, i=0, n=0;
        while(i<l) { n += list[i++]} ;
        return n;
    },
    addFormFilter: function(This, type) {
        This.obj_filter = new TP.formFilter({
            fieldLabel:     'Filter',
            name:           'filter',
            ftype:          type
        });
        This.down('form').add(This.obj_filter);
    },
    /* convert number to binary list */
    dec2bin: function(dec) {
        var potencies = new Array();
        var binary = [];
        for (var i = 0; i > -1; i++) {
            var potency = Math.pow(2, i);
            if (potency > dec) { break; }
            potencies[i] = potency;
        }

        potencies.reverse();

        for (var j = 0; j < potencies.length; j++) {
            var position = potencies[j];
            var zeroOne = parseInt(dec / position);
            if(zeroOne) {
                binary.push(position);
            }
            dec -= potencies[j] * zeroOne;
        }
        return binary;
    },
    /* update an array store with new data */
    updateArrayStore: function(store, data) {
        store.removeAll();
        for(var nr in data) {
            store.loadRawData([[data[nr]]], true);
        }
    },
    /* return location object for url */
    getLocationObject: function(url) {
        var a  = document.createElement('a');
        a.href = url;
        return(a);
    },
    /* compare same origin policy */
    isSameOrigin: function(l1, l2) {
        if(l1.protocol != l2.protocol) {
            return false;
        }
        if(l1.host != l2.host) {
            return false;
        }
        return true;
    },
    /* called on body unload */
    unload: function() {
        try {
            // try saving state
            cp.saveChanges(false);
        }
        catch(e) {}
    },
    deleteDowntime: function(id, panelId, type) {
        var panel = Ext.getCmp(panelId);
        var fields = [{
            fieldLabel: '',
            xtype:      'displayfield',
            value:      'no options needed',
            name:       'display',
            width:      240
        }, {
            xtype: 'hidden', name: 'down_id', value: id
        }];
        var menuCfg = TP.ext_menu_command('Remove', (type == 'host' ? 78 : 79), fields);
        var menu = new Ext.menu.Menu(menuCfg);
        panel.add(menu);
        menu.show();
    }
}
