var hD='0123456789ABCDEF';
function dec2hex(d){
    var h = hD.substr(d & 15, 1);
    
    d >>= 4;
    h = hD.substr(d & 15, 1) + h;
    
    return h;
}

function parseXML(_xml){
    try //Internet Explorer
    {
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    } 
    catch (e) {
        try //Firefox, Mozilla, Opera, etc.
        {
            xmlDoc = document.implementation.createDocument("", "", null);
        } 
        catch (e) {
            //    alert(e.message);
            return null;
        }
    }
    xmlDoc.async = false;
    xmlDoc.load(_xml);
    
    return xmlDoc;
    
}


function RealServerData(){
    //this.ar_raw = new Array;
    
    this.ar_raw = new Array(4, 7, 4, 7, 1, 9, 13, 9, 17, 12, 5, 6, 5, 5, 6, 5, 4, 4, 3, 5, 4, 2, 4, 5, 8, 4, 2, 10, 12, 13, 5, 7, 7, 9, 5, 3, 9, 4, 6, 12, 5, 9, 8, 3, 6, 10, 3, 2, 7, 5, 1, 6, 12, 19, 17, 13, 12, 9, 13, 13, 10, 9, 21, 17, 17, 12, 24, 13, 10, 13, 12, 12);
    /*
     var xml1 = parseXML("http://www.reimage.com/server_data/load_analyzer.xml");
     if (null == xml1)
     return null;
     x = xml1.getElementsByTagName("HOURS")[0].getElementsByTagName("hour");
     var _txt="";
     alert('4');
     for (f = 0;f<x.length;f++)
     {
     */
    /*if (f>0)
     {
     this.ar_raw[f*2-1]=0;
     }
     this.ar_raw[f*2]=parseInt(x[x.length-f-1].childNodes[0].nodeValue);
     if (f>0)
     {
     this.ar_raw[f*2-1]=(this.ar_raw[f]+this.ar_raw[f*2])/2
     }*/
    /*	
     this.ar_raw[f]=parseInt(x[x.length-f-1].childNodes[0].nodeValue);
     
     
     }
     */
    this.ar = new Array();
    /*var d = new Date()
     var gmtHours = d.getTimezoneOffset()/60;
     */
    // the server is in EST (GMT-4)
    
    var _timezone = 1 * 3; //shift the graph so that NOW will be in the middle // (24-(4-gmtHours))*3*2; // est to ours 6 hours *3 of 20 minutes
    for (i = 0; i < this.ar_raw.length - 1; i++) {
        this.ar[i] = 0;
        // smoothing
        for (j = 0; j < 5; j++) {
            pos = i + j + _timezone;
            if (pos >= ar_raw.length) {
                pos -= ar_raw.length;
            }   
            this.ar[i] += this.ar_raw[pos];
        }    
    }
    
    // normalize
    max_val = 0;
    
    for (i = 0; i < this.ar.length; i++) {
        if (this.ar[i] > max_val) 
            max_val = ar[i];
    }
	
    for (i = 0; i < this.ar.length; i++) {
        this.ar[i] = (this.ar[i] / max_val) * 80;
    }
    
    // add next hour empty
    this.ar[i] = 0;
    this.ar[i + 1] = 0;
    this.ar[i + 2] = 0;
    
    return this.ar;
}




// builds an array with data
function CreateExpArray(show_i,max_i)
{
	this.ar = new Array();
	for (i=0;i<max_i;i++) 
	{
		this.ar[i] = i*i;	
	}
	
	// normalize
	max_val=0;

	for (i = 0; i<this.ar.length; i++)
	{
		if (this.ar[i]>max_val) max_val = this.ar[i];
	}

	for (i = 0; i<this.ar.length; i++)
	{
		this.ar[i]=(this.ar[i]/max_val)*100;
	}
	
	// after normalizing
	
	for (i=show_i+1;i<max_i;i++) // every 15 minutes
	{
		this.ar[i] = 0;	
	}
	
	return this.ar;	
}

function DrawGraphX(oElement, max_y,arData, arTexts, tTitle, markZeros)
{
	this.jg = new jsGraphics(oElement);
	this._markZeros = markZeros;
		
	this.drawGraph = function()
	{
		this.max_y=max_y;
		this._timer=5;
		this.ar=arData;
		this.max_x = this.ar.length*7;
		this.max_k=10;

		this.jg.setColor("#000000");	
		this.jg.fillRect(0,0,this.max_x,this.max_y+43);
		
		this.jg.setColor("#2f2f2f");	
		this.jg.fillRect(0,0,this.max_x,this.max_y+20);
		
		this.jg.setStroke(1);
		
		this.jg.setColor("#4f4f4f");	
		for (this.i=0;this.i<this.ar.length;this.i++)
		{
			this.jg.fillRect(this.i*7, 0, 5,this.max_y+1);
		}
		
		this.jg.setColor("#afafaf");
	
		for(this.k=0;this.k<arTexts.length;this.k++)
		{
			this.jg.drawString(arTexts[this.k], (this.max_x/(arTexts.length))*(this.k), this.max_y+3);
			
		}
		
		this.jg.setColor("#ffffff");	
		this.jg.setFont("arial","14px",Font.BOLD); 
		this.jg.drawString(tTitle, 10, this.max_y+23); 

		this.jg.paint();
	}
	
	this.phase1_draw = function(i,do_anim) // line
	{
		
		for(this.k=0;this.k<this.max_k;this.k++)
		{
			
			// bar color........: 40,7f,40
			
			if (this._markZeros)
			{
				// goal colors - green to purpule
				this.gr=0x40+Math.round((100-this.ar[i])*(0xff-0x40)/100);
				this.gg=0x7f;
				this.gb=0x40+Math.round((100-this.ar[i])*(0x80-0x40)/100);
			}
			else
			{
				// goal colors - only green
				this.gr=0x40;
				this.gg=0x7f;
				this.gb=0x40;
			}
			
			// backgoround color: 4f,4f,4f
			this.br=0x4f;
			this.bg=0x4f;
			this.bb=0x4f;
						
			// original
			var nValue = this.ar[i];
			if (this._markZeros)
			{
				if (nValue < 5)
					nValue = 5;
			}
			
			this.jg.setColor("#"+dec2hex((this.gr-this.br)*(this.k/this.max_k)+this.br)+dec2hex((this.gg-this.bg)*(this.k/this.max_k)+this.bg)+dec2hex((this.gb-this.bb)*(this.k/this.max_k)+this.bb));
			this._height = ((nValue/100)*this.max_y)/this.max_k;
			
			this.y_start = this.max_y-this._height*(this.k+1);
			this.y_size = this._height;
			
			this.jg.fillRect(i*7, this.y_start, 5,this.y_size+1);
		}
		
		this.jg.paint();
		
		

		if (this.do_anim != 0)
		{
		
			if (i<this.ar.length-1)
			{
				var oThis = this;
				window.setTimeout(function() { oThis.phase1_draw(i+1,1);},this._timer )

			}
			else
			{
				//this.phase2_draw(0); // blink the current hour
				
			}
		}
	}
	

	this.drawGraph();
	this.phase1_draw(0,1);
	
	
}

function printHour(i)
{
	if (i > 23) i -= 24;
	
	if (i==0)
		return "12am";
		
	if (i<12)
		return eval(i)+"am";
		
	i-= 12;
	
	if (i==0)
		return "12pm";
	
	
	return eval(i)+"pm";
	
}

function createServerLoadGraph(oElement)
{
	var d = new Date();
	var now_hour = d.getHours();
	var _data = RealServerData();
	if (null == _data)
		return null;
	
	return new DrawGraphX(
		oElement,
		150, // max_y
		_data,	// prepare the array
		new Array(
		printHour(now_hour+3),printHour(now_hour+6),printHour(now_hour+9),
		printHour(now_hour+12), printHour(now_hour+15),printHour(now_hour+18),
		printHour(now_hour+21), "NOW"
		),
		"Daily Service Load (last 24 hours)",
		false
	);	
}


function showSecurityGraph(oElement, nSecurity)
{
	if (nSecurity < 10)
		nSecurity  = 10;
		
	return new DrawGraphX(
		oElement,
		75, // max_y
		CreateExpArray(Math.round(nSecurity/2), 50),	// prepare the array
		new Array("Dangerous", "OK", "Safe"),
		"Security",
		true
	);
}

function showStabilityGraph(oElement, nStability)
{			  
	if (nStability < 10)
		nStability = 10;
		
	return new DrawGraphX(
		oElement,
		75, // max_y
		CreateExpArray(Math.round(nStability/2), 50),	// prepare the array
		new Array("Unstable", "Partially Stable","Stable"),
		"Stability",
		true
	);
}	  

function showPerformanceGraph(oElement, nPerformance)
{
	if (nPerformance < 10)
		nPerformance = 10;
		
	return new DrawGraphX(
		oElement,
		75, // max_y
		CreateExpArray(Math.round(nPerformance/2), 50),	// prepare the array
		new Array("Slow", "Medium", "Fast"),
		"Performance",
		true
	);
}

function showOverallGraph(oElement, nOverall)
{
	if (nOverall < 10)
		nOverall = 10;
		
	return new DrawGraphX(
		oElement,
		313, // max_y
		CreateExpArray(Math.round(nOverall/2), 50),	// prepare the array
		new Array("Dysfunctional","Mediocre","Functional"),
		"Overall PC Grade",
		true
	);
}

function Color(r, g, b)
{
	this.r = r;
	this.g = g;
	this.b = b;
}

Color.prototype.blend = function(oColor2, nAlpha)
{
	var nInvAlpha = 1.0 - nAlpha;
	this.r = this.r * nInvAlpha + oColor2.r * nAlpha;
	this.g = this.g * nInvAlpha + oColor2.g * nAlpha;
	this.b = this.b * nInvAlpha + oColor2.b * nAlpha;
}

function toHexString(n, nDigits)
{
	var sResult = Math.round(n).toString(16);
	for (var i = 0; i < nDigits-sResult.length; ++i)
		sResult = "0" + sResult;
	
	return sResult;
}

Color.prototype.toString = function()
{
	return "#" + toHexString(this.r) + toHexString(this.g) + toHexString(this.b);
}

function colorToRGB(sColor)
{
	if ("#" == sColor.charAt(0))
	{
		return new Color(
			parseInt(sColor.substr(1, 2), 16),
			parseInt(sColor.substr(3, 2), 16),
			parseInt(sColor.substr(5, 2), 16)
		);
	}
	
	return null;
}

function ComparisonGraph_Entry(sTitle, nValue, sColor, sValueText)
{
	this.sTitle = sTitle;
	this.nValue = nValue;
	this.oColor = colorToRGB(sColor);
	if (typeof(sValueText) == "undefined")
		this.sValueText = numberToString(nValue);
	else
		this.sValueText = sValueText;
	this.onDone = null;
}

function ComparisonGraph(oElement)
{
	this.oElement = oElement;
	this.oElement.style.position = "relative";
	this.aEntries = new Array();
}

ComparisonGraph.prototype.addEntry = function(sTitle, nValue, sColor, sValueText)
{
	this.aEntries.push( new ComparisonGraph_Entry(sTitle, nValue, sColor, sValueText) );
}

ComparisonGraph.prototype.start = function()
{
	var oBar = document.createElement("div");
//	oBar.style.position = "relative";
	oBar.style.visibility = "hidden";
	oBar.style.width = "100%";
	oBar.style.paddingRight = "5px";
	this.oElement.appendChild(oBar);
	
	var nMax = 0;
	for (var i = 0; i < this.aEntries.length; ++i)
	{
		nMax = Math.max(nMax, this.aEntries[i].nValue);
	}
	
	for (var i = 0; i < this.aEntries.length; ++i)
	{
		this.aEntries[i].drawBar(this.oElement, nMax);
	}
	
	var oAxis = document.createElement("div");
	oAxis.style.position = "relative";
	this.oElement.appendChild(oAxis);
	
	var oAxisLine = document.createElement("div");
	oAxisLine.style.position = "relative";
	oAxisLine.style.left = "0px";
	oAxisLine.style.top = "0px";
	oAxisLine.style.width = "100%";
	oAxisLine.style.borderTopWidth = "2px";
	oAxisLine.style.borderTopStyle = "solid";
	oAxisLine.style.borderTopColor = "black";
	oAxis.appendChild(oAxisLine);

	var aTickLeft = new Array();
	for (var i = 0; i < this.aEntries.length; ++i)
	{
		aTickLeft[i] = new Object();
		aTickLeft[i].x = this.oElement.clientWidth * this.aEntries[i].nValue / nMax;
		aTickLeft[i].index = i;
	}
	aTickLeft.sort(function(a,b){return a.x - b.x});
	
	var aShowLabel = new Array();
	aShowLabel[aTickLeft[0].index] = true;
	for (var i = 1; i < this.aEntries.length; ++i)
	{
		aShowLabel[aTickLeft[i].index] = ((aTickLeft[i].x - aTickLeft[i-1].x) > 100);
	}
	
	for (var i = 0; i < this.aEntries.length; ++i)
	{
		this.aEntries[i].drawTick(oAxis, nMax, aShowLabel[i]);
	}

	if (this.aEntries.length > 0)
	{
		var oThis = this;
		this.nBarIndex = 0;
		
		this.aEntries[0].onDone = function()
		{
			++oThis.nBarIndex;
			
			if (oThis.nBarIndex < oThis.aEntries.length)
				oThis.aEntries[oThis.nBarIndex].start();
			else if (null != oThis.onDone)
				oThis.onDone();
		};
		for (var i = 1; i < this.aEntries.length; ++i)
			this.aEntries[i].onDone = this.aEntries[0].onDone;
		this.aEntries[0].start();
	}
}

function numberToString(n)
{
	n = Math.round(n);
	
	var s = "";

	do
	{
		if (s.length > 0)
			s = "," + s;
			
		var m = (n % 1000).toString(10);
		if (n >= 1000)
		{
			var l = m.length;
			for (var i = 0; i < 3 - l; ++i)
				m = "0" + m;
		}
		
		s = m + s;
		if (n < 1000)
			n = 0;
		else
			n = Math.floor(n / 1000);
	} while(n > 0);
	
	return s;
}

ComparisonGraph_Entry.prototype.drawTick = function(oElement, nMax, bShowLabel)
{
	var oTick = document.createElement("div");
	oTick.style.position = "absolute";
	oTick.style.visibility = "hidden";
	oTick.style.top = "2px";
	oTick.style.left = (100*this.nValue/nMax-1).toFixed(1) + "%";
	oTick.style.borderLeftWidth = "2px";
	oTick.style.borderLeftStyle = "solid";
	oTick.style.borderLeftColor = "white";
	oTick.style.width = "2px";
	oTick.style.height = "10px";
	oTick.style.overflowX = "hidden";
	oTick.style.overflowY = "hidden";
	oElement.appendChild(oTick);

	var oTickLabel = document.createElement("div");
	oTickLabel.style.color = "white";
	oTickLabel.style.position = "absolute";
	oTickLabel.style.visibility = "hidden";
	oTickLabel.style.top = "15px";
	oTickLabel.style.left = (100*this.nValue/nMax-1).toFixed(1) + "%";

	var oTickLabelText = document.createElement("div");
	oTickLabelText.style.position = "relative";
	oTickLabelText.style.left = "-20px";
	
	if (bShowLabel)
		oTickLabelText.innerHTML = this.sValueText;
		//oTickLabelText.innerText = this.sValueText;
		

	oTickLabel.appendChild(oTickLabelText);

	oElement.appendChild(oTickLabel);

	this.oTick = oTick;;
	this.oTickLabel = oTickLabel;
}
	
ComparisonGraph_Entry.prototype.drawBar = function(oElement, nMax)
{
	var oGray = new Color(64, 64, 64);
	
	var oBar = document.createElement("div");
	oBar.style.position = "relative";
	oBar.style.visibility = "hidden";
	oBar.style.width = "100%";
	
	var oShadow = document.createElement("div");
	oShadow.style.width = (100*this.nValue/nMax).toFixed(1) + "%";
	oShadow.style.paddingBottom = "5px";
	oShadow.style.paddingRight = "5px";
	if (oShadow.style.filter)
		oShadow.style.filter = "shadow(color=silver, strength=5, direction=135);";
	oBar.appendChild(oShadow);
	
	
	var oBorder = document.createElement("div");
	oBorder.style.borderWidth = "1px";
	oBorder.style.borderStyle = "solid";
	
	var color = this.oColor.toString();
	var borderColor = 'black';
	switch (color){
		case '#d63e15':
			borderColor = '#a23113';
			break;
		
		case '#d7cc2a':
			borderColor = '#8c8635';
			break;
			
		case '#4cbd19':
			borderColor = '#467f2d';
			break;
	}
	oBorder.style.borderColor = borderColor;
	oShadow.appendChild(oBorder);
	
	var oColor2 = new Color(this.oColor.r, this.oColor.g, this.oColor.b);
	oColor2.blend(oGray, 0.5);
	
	var oGradient = document.createElement("div");
	oGradient.style.height = "15px";
	if (oGradient.style.filter)
		oGradient.style.filter = "filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=1, StartColorStr="+this.oColor.toString()+", EndColorStr="+oColor2.toString()+");";
	else
		oGradient.style.backgroundColor = this.oColor.toString();
	
	oBorder.appendChild(oGradient);
	
	var oText = document.createElement("div");
	oText.style.position = "absolute";
	oText.style.left = "1px";
	oText.style.top = "1px";
	oText.style.paddingLeft = "5px";
	oText.style.overflowY = "hidden";
//	oText.innerText = this.sTitle;
	oText.innerHTML = this.sTitle;
	oText.style.lineHeight = "15px";
	oText.style.visibility = "hidden";
	oBar.appendChild(oText);
	
	oElement.appendChild(oBar);
	
	this.oBar = oBar;
	this.oText = oText;
}

ComparisonGraph_Entry.prototype.start = function()
{
//	if (this.oBar.style.filter)
//		this.oBar.style.filter = "alpha (opacity=0)";
//	else
//		this.oBar.style.opacity = 0;
	this.oBar.style.filter = "alpha (opacity=0)";
		
	this.oBar.style.visibility = "";
	this.oTick.style.visibility = "";
	this.oTickLabel.style.visibility = "";
	
	var oThis = this;
	
	this.nOpacity = 0;
	this.oInterval = window.setInterval(function()
	{
		if (oThis.oBar.filters){
			if (oThis.oBar.filters.alpha.opacity >= 100)
			{
				oThis.oBar.style.filter = "";
				oThis.oTickLabel.style.color = "black";
				oThis.oTick.style.borderLeftColor = oThis.oTickLabel.style.color;
				oThis.oText.style.visibility = "";
				
				window.clearInterval(oThis.oInterval);
				oThis.oInterval = null;
				
				if (null != oThis.onDone)
					oThis.onDone();
			}
			else
			{
				oThis.nOpacity += Math.max(1, (100 - oThis.nOpacity) / 10);
				oThis.oBar.filters.alpha.opacity = oThis.nOpacity;
				
				var nIntensity = (100. - oThis.oBar.filters.alpha.opacity) * 255 / 100.;
				oThis.oTickLabel.style.color = (new Color(nIntensity, nIntensity, nIntensity)).toString();
				oThis.oTick.style.borderLeftColor = oThis.oTickLabel.style.color;
				oThis.oBar.style.width = oThis.oBar.filters.alpha.opacity + "%";
			}
		}else{
			if (oThis.oBar.style.opacity >= 100)
			{
				oThis.oTickLabel.style.color = "black";
				oThis.oTick.style.borderLeftColor = oThis.oTickLabel.style.color;
				oThis.oText.style.visibility = "";
				
				window.clearInterval(oThis.oInterval);
				oThis.oInterval = null;
				
				if (null != oThis.onDone)
					oThis.onDone();
			}
			else
			{
				oThis.nOpacity += Math.max(1, (100 - oThis.nOpacity) / 10);
				oThis.oBar.style.opacity = oThis.nOpacity;
				
				var nIntensity = (100. - oThis.oBar.style.opacity) * 255 / 100.;
				oThis.oTickLabel.style.color = (new Color(nIntensity, nIntensity, nIntensity)).toString();
				oThis.oTick.style.borderLeftColor = oThis.oTickLabel.style.color;
				oThis.oBar.style.width = oThis.oBar.style.opacity + "%";
			}
		}
	}, 50);
}


