/**
 * Application js file
 * 
 * This file contains the Application wide javascript. It contains js code which is
 * used on many pages
 * @author Abbas Ali <abbas@sanisoft.com>
 * @version 1.0
 * @package kanari
 */
// Set the Ext blank image url
Ext.BLANK_IMAGE_URL = base_url + 'js/extjs/resources/images/default/s.gif';

var POUNDS_PER_KG = 2.20462262;
var CMS_PER_INCH = 2.54;

var lastAjaxRequestObj = null;
var lastAjaxRequest = null;
var lastAjaxResponse = null;
var windowLoaded = false;

Ext.onReady(function(){
	setTimeout(function() {
		windowLoaded = true;
	}, 500);	
});


// Taken from http://helephant.com/2007/05/diy-javascript-stack-trace/
// This helps with error stack tracing.
Function.prototype.trace = function()
{
	var trace = [];
	var traceStr = '';
	var current = this;
	while(current)
	{
		var sig = current.signature();
		trace.push(sig);
		traceStr += (sig + "\n");
		current = current.caller;
	}
	return traceStr;
}
Function.prototype.signature = function()
{
	var signature = {
		name: this.getName(),
		params: [],
		toString: function()
		{
			var params = this.params.length > 0 ? 
				"'" + this.params.join("', '") + "'" : "";
			return this.name + "(" + params + ")"
		}
	};
	if(this.arguments)
	{
		for(var x=0; x<this.arguments.length; x++)
			signature.params.push(this.arguments[x]);
	}
	return signature;
}
Function.prototype.getName = function()
{
	if(this.name)
		return this.name;
	var definition = this.toString().split("\n")[0];
	var exp = /^function ([^\s(]+).+/;
	if(exp.test(definition))
		return definition.split("\n")[0].replace(exp, "$1") || "anonymous";
	return "anonymous";
}
/*
// An example of how to use this code:
function a(moo)
{
	var trace = arguments.callee.trace();
	document.getElementById("output").innerHTML = trace.join("<br/>\n");
}
*/


var getExtraInfoFromResponse = function(response) {
	var extraInfo = '';
	try {
		extraInfo += 'Response text: ' + response.responseText + "\n\n";
		extraInfo += 'Response status: ' + response.status + ' (' +  response.statusText + ")\n\n";
		extraInfo += 'Response headers: ' + response.getAllResponseHeaders() + "\n\n";
	} catch (e) {
	}
	return extraInfo;
}

var getExtraInfoFromRequest = function(o) {
	var extraInfo = '';
	try {
		if ('url' in o) {
			extraInfo += 'Request url: ' + o.url+ "\n";
		}
		if ('params' in o) {
			extraInfo += 'Request params: ' + Ext.util.JSON.encode(o.params) + "\n\n";
		}		
		extraInfo += getExtraInfoFromResponse(response);
	} catch(e) {
		
	}
	return extraInfo;
}

var hasNativeJson = function() {	
	try {
		JSON.parse('{}');
		return true;
	} catch (e) {
		return false;
	}
}

var decodeJsonCheckErr = function(text) {	
	try {
		var json;
		if (hasNativeJson()) {
			json = JSON.parse(text);
		} else {
			json = Ext.decode(text);
		}
		return json;
	} catch (e) {
		var extraInfo = '';
		try {	
			if (lastAjaxRequest != null) {
				extraInfo += "Last Ajax Request:\n";
				extraInfo += getExtraInfoFromRequest(lastAjaxRequest);
			}			
			
			if (lastAjaxResponse != null) {
				extraInfo += "Last Ajax Response:\n";
				extraInfo += getExtraInfoFromResponse(lastAjaxResponse);
			}
	
		} catch (e) {
		}
		appExHandler(e, extraInfo);
		
		// I was thinking about limiting this throw to just IE and Firefox (since only they support window.onerror
		// but I think it makes sense to throw for other browsers too.
		//if (navigator.userAgent.indexOf("Firefox")!=-1 || navigator.userAgent.indexOf("MSIE")!=-1)		
		throw "decodeJsonCheckErrThrow";
	}
}

var appLoadExceptionHandler = function(store, o, response, ex) {	
	var extraInfo = getExtraInfoFromRequest(o) + getExtraInfoFromResponse(response);	
	appExHandler(ex, extraInfo);
}

var appExHandler = function(ex, extraInfo) {
	var msg = '';
	var url = '';
	var linenumber = '';	
	try {
		if ('name' in ex) {
			msg = 'Name: ' + ex.name + ': ';
		}
		if ('message' in ex) {
			msg = msg + ex.message;		
		}
		if ('description' in ex) {
			msg = msg + ' ' + ex.description;
		}
		if ('fileName' in ex) {
			url = ex.fileName;
		}
		if ('lineNumber' in ex) {
			linenumber = ex.lineNumber;
		}
	} catch (e) {
	}
	appErrorHandler(msg, url, linenumber, ex, extraInfo);
}

var appErrorHandler = function (msg, url, linenumber, ex, extraInfo, wasFromTimeout) {	
	var decodeJsonCheckErrThrowRegExp = /.*decodeJsonCheckErrThrow.*/i;
	if (decodeJsonCheckErrThrowRegExp.test(msg)) {
		// Do nothing. This was just to allow the code to be aborted in the case of the JSON decoding.
		return true;
	}

	try {
		var errMsg = 'A program error occurred. Its details are being sent to the Wagmu team. Please try your action again or <a href="/wagmu_comment.php" target="_blank">contact support</a>.';
		if (windowLoaded) {
			remove_indicator_messages();		
			add_message(errMsg, 'program_error');
		} else {			
			// This timeout stuff is necessary becauase the ExtJS window load handler was getting fired
			// when the stack trace code threw an exception and then it wasn't coming back to the catch of the 
			// stack trace code.			
			if (wasFromTimeout) {			
				setTimeout(function(){
					try {
						errMsg = 'A program error occurred. Please try your action again or <a href="/wagmu_comment.php" target="_blank">contact support</a>.';
						remove_indicator_messages();		
						add_message(errMsg, 'program_error');					
					}catch(e){
					}
				}, 1000);
			} else {
				setTimeout(function() {
					appErrorHandler(msg, url, linenumber, ex, extraInfo, true)
				}, 2000);
				return true;
			}
		}
	} catch (e) {		
		// Not much we can do here if an error happens in the error handler.
	}		
	
	var exStack = '';
	try {
		if (ex != undefined && 'stack' in ex) {
			exStack = ex.stack;
			var maxExStackLen = 3000;
			if (exStack.length > maxExStackLen) {
				exStack = exStack.substring(0, maxExStackLen) + "\n...\n";
			}
		}
	} catch (e) {
	}
		
	var stackPrinted = '';
	try {		
		//This was causing me an issue because of how it needed to raise an exception, but I hopefully
		//fixed it with the setTimeout stuff above.
		// I later learned that it is an issue in other cases, sometimes
		//var stackArray = printStackTrace({e: ex, guess: false});
		//for (var i = 0; i < stackArray.length; i++) {
		//	stackPrinted += stackArray[i] + "\n\n";
		//}		
	} catch (e) {
	}
	
	var traceStack = '';
	try {
		// Found an issue with it taking a long time.
		//traceStack = arguments.callee.trace();
	} catch (e) {
	}
	
	try {
		Ext.Ajax.request({
			url: base_url + 'log_error.php'
			, params: {
				msg: msg
				, file: (url + ':' + linenumber)
				// This is from stacktrace.js
				, stackPrinted: stackPrinted
				, traceStack: traceStack
				, exStack: exStack				
				, extraInfo: extraInfo
			}
			, success: function(response) {				
			}
			, failure: function() {							
			}
		});
	} catch (e) {		
	}
	
	return true;
};

window.onerror = appErrorHandler;

// This is used in conjunction with the datesToEmphasize custom property of a DatePicker.

function parseDatesToEmphasize(datesArray, cssClass) {
	if (!cssClass) {
		cssClass = "x-date-emphasize";
	}

	var datesToEmphasize = eval('({})');
	
	var parts;
	for (var i = 0; i < datesArray.length; i++) {
		datesToEmphasize[parseDateAndGetOnlyDatepart(datesArray[i]).getTime()] = cssClass;
	}			
	return datesToEmphasize;
}

function mergeDatesToEmphasize(picker, datesArray, cssClass) {
	for (var i = 0; i < datesArray.length; i++) {
		addDateToEmphasize(picker, parseDateAndGetOnlyDatepart(datesArray[i]), cssClass);
	}
}

function addDateToEmphasize(picker, d, cssClass) {
	if (!cssClass) {
		cssClass = "x-date-emphasize";
	}

	var dateObj = getDatePartOnly(d);
		
	if ('datesToEmphasize' in picker) {
		var curVal = picker.datesToEmphasize[dateObj.getTime()];
		if (!curVal) {	
			picker.datesToEmphasize[dateObj.getTime()] = cssClass;
		} else {
			var classes = curVal.split(' ');
			var found = false;
			for (var i = 0; i < classes.length; i++) {
				if (classes[i] == cssClass) {
					found = true;					
				}
			}
			
			if (!found) {
				picker.datesToEmphasize[dateObj.getTime()] += (" " + cssClass);
			}
		}
	} else {
		var datesToEmphasize = eval('({})');
		datesToEmphasize[dateObj.getTime()] = cssClass;
		picker.datesToEmphasize = datesToEmphasize;
	}
}

function parseDateAndGetOnlyDatepart(str) {
	var dateObj = new Date();
	dateObj.setHours(0);
	dateObj.setMinutes(0);
	dateObj.setSeconds(0);
	dateObj.setMilliseconds(0);
	
	var parts = str.split('-');
	dateObj.setYear(parts[0]);
	dateObj.setMonth(parts[1] - 1);
	dateObj.setDate(parts[2]);	
	
	return dateObj;
}

function getDatePartOnly(d) {
	var dateObj = new Date();
	dateObj.setHours(0);
	dateObj.setMinutes(0);
	dateObj.setSeconds(0);
	dateObj.setMilliseconds(0);
	
	dateObj.setYear(d.getFullYear());
	dateObj.setMonth(d.getMonth());
	dateObj.setDate(d.getDate());
	return dateObj;
}



// Taken from:
// http://www.extjs.com/forum/showthread.php?6568-localpart-of-email-regex-not-conformant-to-rfc
// and http://www.extjs.com/forum/archive/index.php/t-4271.html
// Sadly this doesn't seem to work in IE, but it was trying to allow special characters in email address. I just do the validation on the server-side instead.
//Ext.form.VTypes["email"] = /^([\w\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]+)(.[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
//Ext.form.VTypes["emailMask"] = /[a-z0-9_\.\-@\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~]/i;

// Make it so that you can't collapse the grouping view controls.
Ext.override(Ext.grid.GroupingView, {interceptMouse: Ext.emptyFn});

// This will make it so that if you specify labelWidth: 'auto' for a FormPanel, then the labels will automatically resize to 
// match their text rather than having a fixed specified width.
// Taken from:  https://www.extjs.com/forum/showthread.php?58530-FormPanel-fluid-label-width
Ext.override(Ext.form.FormPanel, {
    initFields : function(){
        var labelMetrics = Ext.getBody().createChild({
            cls: 'x-form-item x-hide-offsets',
            cn: {
                tag: 'label',
                style: {
                    width: 'auto'
                }
            }
        }, null, true);
        label = labelMetrics.firstChild;

        var f = this.form;
        var formPanel = this;
        if (this.labelWidth == 'auto') {
            this.labelWidth = 0;
            this.autoLabelWidth = true;
        }
        var fn = function(c){
            if(c.isFormField){
                f.add(c);
                if (c.fieldLabel && this.autoLabelWidth) {
                    label.innerHTML = c.fieldLabel + (this.labelSeparator || ':');
                    this.labelWidth = Math.max(this.labelWidth, labelMetrics.offsetWidth);
                }
            }else if(c.doLayout && c != formPanel){
                Ext.applyIf(c, {
                    labelAlign: this.labelAlign,
                    labelWidth: this.autoLabelWidth ? 'auto' : this.labelWidth,
                    itemCls: this.itemCls
                });
                if (c.labelWidth == 'auto') {
                    c.labelWidth = 0;
                    c.autoLabelWidth = true;
                }

                if(c.items){
                    c.items.each(fn, c);
                }
            }
        }
        this.items.each(fn, this);
        
        if (this.topToolbar) {
            fn(this.topToolbar);
        }
        if (this.bottomToolbar) {
            fn(this.bottomToolbar);
        }
        if (this.fbar) {
            fn(this.fbar);
        }
    }
});

// Override the onRender of datepicker to show a cancel button
Ext.override(Ext.DatePicker, {
    onRender : function(container, position){
        var m = [
             '<table cellspacing="0">',
                '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
                '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
        var dn = this.dayNames;
        for(var i = 0; i < 7; i++){
            var d = this.startDay+i;
            if(d > 6){
                d = d-7;
            }
            m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
        }
        m[m.length] = "</tr></thead><tbody><tr>";
        for(var i = 0; i < 42; i++) {
            if(i % 7 == 0 && i != 0){
                m[m.length] = "</tr><tr>";
            }
            m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
        }
        m[m.length] = '</tr></tbody></table></td></tr><tr><td colspan="3" class="x-date-bottom" align="center"></td></tr></table><div class="x-date-mp"></div>';

        var el = document.createElement("div");
        el.className = "x-date-picker";
		
		// This makes the date picker correctly sized in Firefox 3.
		el.style.width = '10px';

        el.innerHTML = m.join("");

        container.dom.insertBefore(el, position);

        this.el = Ext.get(el);
        this.eventEl = Ext.get(el.firstChild);

        new Ext.util.ClickRepeater(this.el.child("td.x-date-left a"), {
            handler: this.showPrevMonth,
            scope: this,
            preventDefault:true,
            stopDefault:true
        });

        new Ext.util.ClickRepeater(this.el.child("td.x-date-right a"), {
            handler: this.showNextMonth,
            scope: this,
            preventDefault:true,
            stopDefault:true
        });

        this.eventEl.on("mousewheel", this.handleMouseWheel,  this);

        this.monthPicker = this.el.down('div.x-date-mp');
        this.monthPicker.enableDisplayMode('block');
        
        var kn = new Ext.KeyNav(this.eventEl, {
            "left" : function(e){
                e.ctrlKey ?
                    this.showPrevMonth() :
                    this.update(this.activeDate.add("d", -1));
            },

            "right" : function(e){
                e.ctrlKey ?
                    this.showNextMonth() :
                    this.update(this.activeDate.add("d", 1));
            },

            "up" : function(e){
                e.ctrlKey ?
                    this.showNextYear() :
                    this.update(this.activeDate.add("d", -7));
            },

            "down" : function(e){
                e.ctrlKey ?
                    this.showPrevYear() :
                    this.update(this.activeDate.add("d", 7));
            },

            "pageUp" : function(e){
                this.showNextMonth();
            },

            "pageDown" : function(e){
                this.showPrevMonth();
            },

            "enter" : function(e){
                e.stopPropagation();
                return true;
            },

            scope : this
        });

        this.eventEl.on("click", this.handleDateClick,  this, {delegate: "a.x-date-date"});

        this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);

        this.el.unselectable();
        
        this.cells = this.el.select("table.x-date-inner tbody td");
        this.textNodes = this.el.query("table.x-date-inner tbody span");

        this.mbtn = new Ext.Button({
            text: "&#160;",
            tooltip: this.monthYearText,
            renderTo: this.el.child("td.x-date-middle", true)
        });

        this.mbtn.on('click', this.showMonthPicker, this);
        this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");

		// #### Added cancel button #### //
        this.cancelButton = new Ext.Button({
            renderTo: this.el.child("td.x-date-bottom", true),
            text: 'Cancel',
            tooltip: 'Cancel datepicker',
            handler: this.hide,
            scope: this
        });
		// ############# //
		
        if(Ext.isIE){
            this.el.repaint();
        }
        this.update(this.value);
    }
});
// Override the Ext CellSelectionModel's onEditorKey function. This is done so that we can make enter key
// behave like tab key in grid


// Most of this code is copied from the ext-all-debug.js version of update except the 
// part where we set bold days.
Ext.override(Ext.DatePicker, {
	update : function(date){		
        var vd = this.activeDate;

        this.activeDate = date;
	
		/*
        if(vd && this.el){

            var t = date.getTime();
			var calThis = this;

            if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){

                this.cells.removeClass("x-date-selected");

                this.cells.each(function(c){

                   if(c.dom.firstChild.dateValue == t){

                       c.addClass("x-date-selected");

                       setTimeout(function(){

                            try{c.dom.firstChild.focus();}catch(e){}

                       }, 50);

                       return false;

                   }
				   
					// Newly added code to allow date bolding.								
					if ('datesToEmphasize' in calThis) {				
						if (calThis.datesToEmphasize[t]) {					
							c.addClass("x-date-emphasize");
						}
					}

                });

                return;

            }

        }
		*/

        var days = date.getDaysInMonth();

        var firstOfMonth = date.getFirstDateOfMonth();

        var startingPos = firstOfMonth.getDay()-this.startDay;



        if(startingPos <= this.startDay){

            startingPos += 7;

        }



        var pm = date.add("mo", -1);

        var prevStart = pm.getDaysInMonth()-startingPos;



        var cells = this.cells.elements;

        var textEls = this.textNodes;

        days += startingPos;



        
        var day = 86400000;

        var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();

        var today = new Date().clearTime().getTime();

        var sel = date.clearTime().getTime();

        var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;

        var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;

        var ddMatch = this.disabledDatesRE;

        var ddText = this.disabledDatesText;

        var ddays = this.disabledDays ? this.disabledDays.join("") : false;

        var ddaysText = this.disabledDaysText;

        var format = this.format;



        var setCellClass = function(cal, cell){

            cell.title = "";

            var t = d.getTime();

            cell.firstChild.dateValue = t;

            if(t == today){

                cell.className += " x-date-today";

                cell.title = cal.todayText;

            }

            if(t == sel){

                cell.className += " x-date-selected";

                setTimeout(function(){

                    try{cell.firstChild.focus();}catch(e){}

                }, 50);

            }

            
            if(t < min) {

                cell.className = " x-date-disabled";

                cell.title = cal.minText;

                return;

            }

            if(t > max) {

                cell.className = " x-date-disabled";

                cell.title = cal.maxText;

                return;

            }

            if(ddays){

                if(ddays.indexOf(d.getDay()) != -1){

                    cell.title = ddaysText;

                    cell.className = " x-date-disabled";

                }

            }

            if(ddMatch && format){

                var fvalue = d.dateFormat(format);

                if(ddMatch.test(fvalue)){

                    cell.title = ddText.replace("%0", fvalue);

                    cell.className = " x-date-disabled";

                }

            }
			
			// Newly added code to allow date bolding.			
			if ('datesToEmphasize' in cal) {			
				var empClass = cal.datesToEmphasize[t];
				if (empClass) {					
					cell.className =  cell.className + " " + empClass;
				}
			}

        };



        var i = 0;

        for(; i < startingPos; i++) {

            textEls[i].innerHTML = (++prevStart);

            d.setDate(d.getDate()+1);

            cells[i].className = "x-date-prevday";
			
            setCellClass(this, cells[i]);

        }

        for(; i < days; i++){

            intDay = i - startingPos + 1;

            textEls[i].innerHTML = (intDay);

            d.setDate(d.getDate()+1);

            cells[i].className = "x-date-active";

            setCellClass(this, cells[i]);

        }

        var extraDays = 0;

        for(; i < 42; i++) {

             textEls[i].innerHTML = (++extraDays);

             d.setDate(d.getDate()+1);

             cells[i].className = "x-date-nextday";

             setCellClass(this, cells[i]);

        }



        this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());



        if(!this.internalRender){

            var main = this.el.dom.firstChild;

            var w = main.offsetWidth;

            this.el.setWidth(w + this.el.getBorderWidth("lr"));

            Ext.fly(main).setWidth(w);

            this.internalRender = true;

            
            
            
            if(Ext.isOpera && !this.secondPass){

                main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";

                this.secondPass = true;

                this.update.defer(10, this, [date]);

            }

        }

    }
});

Ext.override(Ext.grid.CellSelectionModel, {
	onEditorKey : function(field, e){        
        var k = e.getKey(), newCell = null, g = this.grid, ed = g.activeEditor;
        //log_debug_message('onEditorKey:' + k);
                
        if (typeof ed != 'undefined' && ed != null) {        
            var shift = e.shiftKey;
            if(k == e.TAB){
                e.stopEvent();
                if (ed) {
                    ed.completeEdit();            
                    if(shift){
                        newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
                    }else{
                        newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
                    }
                }                
            }else if(k == e.ENTER){
                e.stopEvent();
                if (ed) {
                    ed.completeEdit();
                    if(this.moveEditorOnEnter !== false){
                        if(shift){
                            newCell = g.walkCells(ed.row, ed.col-1, 1, this.acceptsNav, this);
                        }else{
                            newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
                        }
                    }
                }                
            }else if(k == e.ESC){
                e.stopEvent();
                if (ed) {
                    ed.cancelEdit();
                }
            }
            if(newCell != null){                          
                if (ed != null && 'editor' in g.getColumnModel().config[newCell[1]]) {
                    g.startEditing(newCell[0], newCell[1]);
                } else {
                    g.getSelectionModel().select(newCell[0], newCell[1]);
                }
            }
        }
	}
});

// This is a hack to override the editor's onblur function
// This was done as sometimes the quantity field was blurring without any reason. This forces it not to blur.
Ext.override(Ext.Editor, {
    onBlur : function(){
		// If this is quantity column (at 3rd index)
		if (this.col == 3)
		{
			// Extra added code
			if (true == this.field.lock) {
				this.field.focus();
				this.field.lock = false;
				return;
			}
			// end
		}
        if(this.allowBlur !== true && this.editing){
            this.completeEdit();
        }
    }
});

/**
 * Function which gets called when the dom is ready
 */
Ext.onReady(function() {
	// Scroll and remove messages from message panel
	scroll_and_remove_messages();
	// reload the page in 2 hrs
	setTimeout('window.location.reload();', 7200000);       	
	
	Ext.Ajax.addListener('beforerequest', function(obj, o){        
		lastAjaxRequestObj = obj;
		lastAjaxRequest = o;
	});
	
	// Add a listener to ajax request complete and check whether user has been logged out or not
	Ext.Ajax.addListener('requestcomplete', function(conn, response, options){   
		lastAjaxResponse = response;
		
		// If flag to redirect to login is set then redirect the user to login page
		// We are not decoding the json string to object as sometimes the responseText may not be a json string
		// and in such cases the decoding function will give errors.
		if ('{"login_redirect":true}' == response.responseText)
		{
			window.location = base_url;
		}
	});
});

function show_dialog_from_element(elementId) {
    Ext.get('container_shadow').setStyle('display', '');    
    Ext.get('dialog_div').update(Ext.get(elementId).dom.innerHTML);    
    
    /*
    Ext.get('dialog_div').setStyle('left', 
        (Ext.get('container').getWidth() / 2
        - Ext.get('dialog_div').getWidth() / 2) + 'px');
    Ext.get('dialog_div').setStyle('top', 
        (Ext.get('container').getHeight() / 2
        - Ext.get('dialog_div').getHeight() / 2) + 'px');
        */
    Ext.get('dialog_div').setStyle('width', Ext.get(elementId).getStyle('width'));
    Ext.get('dialog_div').setStyle('height', Ext.get(elementId).getStyle('height'));
    Ext.get('dialog_div').setStyle('left', 
        ((Ext.get('container').getWidth() - Ext.get('dialog_div').getWidth()) / 2) + 'px');       
    Ext.get('dialog_div').setStyle('top', Ext.get(elementId).getStyle('top'));

    Ext.get('dialog_div').setStyle('visibility', '');    
    //Ext.get('container_shadow').setStyle('display', 'none');
}

function hide_dialog() {
    Ext.get('dialog_div').setStyle('visibility', 'hidden');
    Ext.get('container_shadow').setStyle('display', 'none');
}

function log_debug_message(msg) {
    try {
        console.log(msg);
    } catch (ex) {  
        add_message('Debug: ' + msg, 'information');
    }
}

/**
 * Function to scroll the message panel to the bottom
 */
function scroll_and_remove_messages()
{
	// Get the message panel div
	var message_panel = Ext.get('message_panel');
	// Scroll the message panel to bottom to show the most recent message
	message_panel.scroll('down', message_panel.dom.scrollHeight, true);
	// Remove the messages if more than 10 in the message panel
	remove_extra_messages();
}
/**
 * Function to remove messages from panel
 * This function checks the total number of messages in panel. If messages are more than
 * max in number than the old messages are removed from panel
 * @param integer Max number of messages that can be hold in the panel
 */
function remove_extra_messages()
{
	// Max number of message the panel can hold
	var max = 10;
	// Get the total number of missages in the message panel
	var total_messages = Ext.query('#message li').length;
	
	// If total number of messages are greater than max than we will delete the extra ones
	if (total_messages >= max)
	{
		// Calculate how many messages needs to be removed
		var loop = total_messages - max;
		
		// Run a loop and remove all older messages which are not needed
		for (i = 1; i <= loop; i++)
		{
			Ext.get('message').first().remove();
		}
	}
}

function remove_indicator_messages()
{
	// Get the total number of missages in the message panel
	var messages = Ext.query('#message li');

	if (0 < messages.length)
	{
		for(i = 0; i < messages.length; i++)
		{
			if (Ext.get(messages[i]).hasClass('indicator'))
			{
				Ext.get(messages[i]).remove();
			}
		}
		// We will remove the old_message class from last message
		var messages = Ext.query('#message li');
        try {
            if (messages.length > 0) {
                Ext.get(messages[messages.length - 1]).removeClass('old_message');
            }
        } catch (ex) {
            // If there are no messages, that will give an error.
        }
	}
}

/**
 * Function to add a new message to the message panel
 * @param string Message to be added
 * @param string Warning level of message
 */
function add_message(message, level)
{
	// We will append the timestamp to the message
	message = new Date().format('g:i a') + '. ' + message;
	// First we will change the old message to gray color
	change_old_messages();
	// Prepare the html string for new li element which will hold the message
	var html = '<li class="message_' + level + '">' + message + '</li>';
	// Insert the li in the message ul at the end
	Ext.get('message').insertHtml('beforeEnd', html);
	// Scroll the message panel to bottom and remove extra messages
	scroll_and_remove_messages();
}

/**
 * Function to trun old messages to gray color
 */
function change_old_messages()
{
	// Get the total number of missages in the message panel
	var messages = Ext.query('#message li');
	
	if (0 < messages.length)
	{
		for(i = 0; i < messages.length; i++)
		{
			Ext.get(messages[i]).addClass('old_message');
		}
	}
}

/**
 * Function to reload the tab contents
 */
function reload_tab(tab)
{
	// If recipes tab needs to be reloaded
	if ('recipes' == tab)
	{
		// Call the destroy method which detroys the form nutrients panel
		recipes.destroy();
		// Call the init method which rebuilds everything
		recipes.init();
	}
	else if ('food_diary' == tab)
	{		
        /*
                    // Reload the food diary grid store
		food_diary.grid().store.reload({
			callback: function() {
				// Reload the food diary nutrients panel in a callback
				food_diary.sort_nutrients_panel('name');
			}
		});
                    */
        
        food_diary.load_last_food_plan();
	}
}

/**
 * Function to prepare and return a array of dates to be used in combobox
 */
function get_dates()
{
	// Initialize the dates array
	var dates = new Array();
	
	// Run a loop for 31 times and prepare the dates array
	for (i = 1;i <=31; i++)
	{
		dates[i-1] = [i];
	}
	
	return dates;
}

/**
 * Function to prepare and return a array of months to be used in combobox
 */
function get_months()
{
	var months = new Array();
	months = [['1', 'Jan'], ['2', 'Feb'], ['3', 'Mar'], ['4', 'Apr'], ['5', 'May'], ['6', 'Jun'], ['7', 'Jul'], ['8', 'Aug'], ['9', 'Sep'], ['10', 'Oct'], ['11', 'Nov'], ['12', 'Dec']];
	return months;
}

function get_years()
{
	// We are getting current year from server side as different browsers give different current year
	var current_year = js_vars.current_year;
	var years = new Array();
	// We will get last 80 years
	for (i = 0; i < 80; i++)
	{
		years[i] = [current_year - i];
	}
	
	return years;
}

/**
 * @class Ext.grid.TableGrid
 * @extends Ext.grid.Grid
 * A Grid which creates itself from an existing HTML table element.
 * @constructor
 * @param {String/HTMLElement/Ext.Element} table The table element from which this grid will be created - 
 * The table MUST have some type of size defined for the grid to fill. The container will be 
 * automatically set to position relative if it isn't already.
 * @param {Object} config A config object that sets properties on this grid and has two additional (optional)
 * properties: fields and columns which allow for customizing data fields and columns for this grid.
 * @history
 * 2007-03-01 Original version by Nige "Animal" White
 * 2007-03-10 jvs Slightly refactored to reuse existing classes
 */
Ext.grid.TableGrid = function(table, config) {
  config = config || {};
  Ext.apply(this, config);
  var cf = config.fields || [], ch = config.columns || [];
  table = Ext.get(table);

  var ct = table.insertSibling();

  var fields = [], cols = [];
  var headers = table.query("thead th");
  for (var i = 0, h; h = headers[i]; i++) {
    var text = h.innerHTML;
    var name = 'tcol-'+i;

    fields.push(Ext.applyIf(cf[i] || {}, {
      name: name,
      mapping: 'td:nth('+(i+1)+')/@innerHTML'
    }));

    cols.push(Ext.applyIf(ch[i] || {}, {
      'header': text,
      'dataIndex': name,
      'width': h.offsetWidth,
      'tooltip': h.title,
      'sortable': true
    }));
  }

  var ds  = new Ext.data.Store({
    reader: new Ext.data.XmlReader({
      record:'tbody tr'
    }, fields)
  });

  ds.loadData(table.dom);

  var cm = new Ext.grid.ColumnModel(cols);

  if (config.width || config.height) {
    ct.setSize(config.width || 'auto', config.height || 'auto');
  } else {
    ct.setWidth(table.getWidth());
  }

  if (config.remove !== false) {
    table.remove();
  }

  Ext.applyIf(this, {
    'ds': ds,
    'cm': cm,
    'sm': new Ext.grid.RowSelectionModel(),
    autoHeight: true,
    autoWidth: false
  });
  Ext.grid.TableGrid.superclass.constructor.call(this, ct, {});
};

Ext.extend(Ext.grid.TableGrid, Ext.grid.GridPanel);

function get_nutrients_panel_grid_obj(table_id)
{   
	return new Ext.grid.TableGrid(table_id, {
	      stripeRows: true // stripe alternate rows
	      , id: table_id + '_grid'
	      , columns: [{
            /* Nutrient */
		  	width: 100
		  }, {
		  	width: 50       
			, sortable: false            
			, align: 'center'
            , hidden: true
		  }, {
		  	width: 50
			, sortable: false
			, align: 'right'
            , hidden: true
		  }, {
		  	width: 50
			, sortable: false
			, align: 'right'
            , hidden: true
		  }, {
		  	width: 50
			, sortable: false
			, align: 'right'
            , hidden: true
		  }, {
            /* %Min Number */
		  	width: 50
			, align: 'right'           
		  }, {
		  	width: 50
			, align: 'right'
			, hidden: true
		  }, {
            /* %Min Bar */
		  	width: 200
			, sortable: false
		  }]
		  , fields: [
		  	{type: 'string'}
			, {type: 'string'}
			, {type: 'string'}
			, {type: 'string'}
			, {type: 'float'}
			, {type: 'float'}
			, {type: 'float'}
		  ]
	});
    
}

