 /**
  * --------------------------------------------------------------------------
  * @description: Convert the Array raw data to the YUI Json Formatted String
  * @author: Ramesh Shrestha
  * @created: 05/08/2009
  * @updated: 22/02/2010
  * @updated: 17/03/2010
  * @copyright: 2009 Framtidsforum I&M AB 
  * --------------------------------------------------------------------------
  */
 
 
 
/**
 * the customize collection class that mimic the real collection object.
 */ 
function Collection() {
    this.arr = new Array();
    this.idx = 0;
    this.add = function(elem) {
        this.arr[this.idx] = elem;
        this.idx++;
    }
    this.item = function(varIdx) {
        return this.arr[varIdx];
    }
    this.count = function() {
        return this.arr.length;
    }
    this.me = function() {
        return this.arr;
    }
}

/**
 * class constructor Feeder Object.
 */
function Feeder(co){
	this.co = co;
}

/**
 * check if the given excel range value is constant or Address value.
 * @param param1:
 * @return
 */
Feeder.prototype.IsConstant = function(param1) {
    var regex = /{.*}/;
    return regex.test(param1)
};
/**
 * check if the given excel range value is Excels Address value.
 * @param varParam:
 * @return
 */
Feeder.prototype.isXLAddress = function(varParam){
	var regex=/(?:\$.*\w.*\d)/;
	return regex.test(varParam);
}
/**
  * generates the jsonformat data for YUI base chart
  * @param sheetid:
  * @param chartid:
  * @param arrValueid:
  * @param categoryid:
  * @return 
  */ 
Feeder.prototype.getFormatSeriesData = function(sheetid, chartid, arrValueid, categoryid) {
    var arrSeries = new Array();
    if (isArray(categoryid)) {
        //static data.
        arrSeries[0] = categoryid;
    }
    else {
        arrSeries[0] = getCategory(categoryid);
    }
    var lenArrValueid = arrValueid.length;
    for (var seriesIndx = 0; seriesIndx < lenArrValueid; seriesIndx++) {
        if (isArray(arrValueid[seriesIndx]))
            arrSeries[seriesIndx + 1] = arrValueid[seriesIndx];
        else {
            arrSeries[seriesIndx + 1] = getValue(arrValueid[seriesIndx]);
        }
    }
    var lenArrSeries = arrSeries.length;
    var arrdataSource = new Array();
    var lenCaption = arrSeries[0].length;
    for (var indx = 0; indx < lenCaption; indx++) {
        var arrTmp = new Object();
        for (var i = 0; i < lenArrSeries; i++) {
            arrTmp["series" + i] = arrSeries[i][indx];
        }
        arrdataSource[indx] = arrTmp;
    }
    return arrdataSource;
}

/**
 * problem: 
 *Object.prototype.objectType = function()
 *{
 *var obType = String(this.constructor).match(/function\s+(\w+)/);
 *
 *if(obType) return obType[1];
 *return "undefined"; // just in case...
 *}
 */

/**
 *
 * @param strRange:
 * @return 
 */
Feeder.prototype.getArray=function(strRange){	
	//..
	if(this.isArray(strRange))
	{
		strRange = strRange[0];//take the 1st index element;	
	}
	//..
	if(this.IsConstant(strRange))
	{
		return this.toArray(strRange);
	}
	else{
		var refArr =co[strRange];
		if (typeof (refArr) == "undefined")
            throw "FeederCustomArrayException";
		var arr = new Array();
		var lenXRange = refArr.length;
		var i=0;
        for (var indx0 = 0; indx0 < lenXRange; indx0++)
		{
			var lenD2 = refArr[indx0].length
            for (var indx1 = 0; indx1 < lenD2; indx1++)
			{
				//arr[i] = filterNaN(refArr[indx0][indx1]);
				arr[i] = this.tryVerifyData(refArr[indx0][indx1]);
				i++;
			}
		}
		return arr;
	}
};

/**
 * @Ramesh: @modified:june\22,10
 * @param arg:(string)
 * @return: (string)
 * */
Feeder.prototype.tryVerifyData=function(arg)
{
	if(isFinite(arg))
	{
		return this.roundDec(Number(arg),3);
	}
	else
	{
		if(typeof(arg) == 'string')
		{
			return arg;	
		}
		else
		{
			return 0;
		}
	}	
};

/**
 * @Ramesh: @Created: June\22,10
 * Number Concanate and Rounding
 * @param numIn:(String) Input Number
 * @param decimalPlace: (int) fix rounding
 * */	
Feeder.prototype.roundDec=function(numIn, decimalPlaces){
	//var nExp = Math.pow(10,decimalPlaces) ;
	var nRetVal = Math.round(numIn * Math.pow(10,decimalPlaces)) / Math.pow(10,decimalPlaces) ;
	return nRetVal;
};
/*end*/

/**
 * @desc: makes the series of constant array out of number of value.
 * @param strRange: datarange address
 * @return:constant object of value ie, {1,2,3,4,5}
 * @created: 17/03/2010 
 */
Feeder.prototype.getConstantArray=function(strRange)
{	
	var refArr =co[strRange];
	var arr = new Array();
	var lenXRange = refArr.length;
	var i=0;
    for (var indx0 = 0; indx0 < lenXRange; indx0++)
	{
		var lenD2 = refArr[indx0].length
        for (var indx1 = 0; indx1 < lenD2; indx1++)
		{
			arr[i] = i + 1;
			i++;
		}
	}
	return '{'+arr.join(",")+'}';
};

/**
 * converts the string having the formt of {"""""} to ["""""]
 * @strRange string of range of valuesdata
 * @return string valuedata
 */
Feeder.prototype.toArray = function(strRange) {
    var strParse = strRange.replace(/[\{-]/g, "[");
    strParse = strParse.replace(/[\}-]/g, "]");
    return eval(strParse); 
}

/**
 *
 * @param cellRange:
 * @return 
 */
Feeder.prototype.getValue = function(cellRange) {
    var arrTmp = new Array();
    var i = 0;
    for (var indx0 = 0; indx0 < co[cellRange].length; indx0++)
        for (var indx1 = 0; indx1 < co[cellRange][indx0].length; indx1++)
		{
			var _var = (co[cellRange][indx0][indx1]);
			if(isFinite(_var)){
				arrTmp[i++] = _var;//(co[cellRange][indx0][indx1]);
			}
			else{
				arrTmp[i++]=0;
			}
		}
    return arrTmp;
}

/**
 * check for the object as array
 * @param obj: script object to check
 * @return boolen value
 */ 
Feeder.prototype.isArray=function(obj) {
    return (obj.constructor.toString().indexOf("Array") != -1);
}

/**
 * value item_element object for radar element use for json format 
 * @param y: datavalue
 * @retun object
 */
Feeder.prototype.radar=function(y) {
    return y;
}

/**
 * value item_element object for line chart element use for json format 
 * @param y: datavalue
 * @retun object
 */
Feeder.prototype.line=function(y) {
    return y;
}

/**
 * value item_element object for column chart element use for json format 
 * @param y: datavalue
 * @retun object
 */
Feeder.prototype.column=function(y) {
    return y;
}

/**
 * generate and format the string for the axis label
 * @param y: value
 * @param fmtCode: formating code
 * @return formated string
 */
Feeder.prototype.label=function(y,fmtCode){
	if(isFinite(y))
	{
		if(fmtCode != undefined)
		{
			if(fmtCode.length > 0)
			{
				y = eedatefmt(fmtCode,y) + '';
			}
			else
			{
				y += '';
			}
		}
		else
		{
			y += '';
		}
	}
	return y;
}

/**
 * value item_element object for bar chart element use for json format 
 * @param y: datavalue
 * @retun object
 */
Feeder.prototype.bar=function(y)
{
	var oProperty={};
	oProperty["right"]=y;
	return  oProperty;//"{\"right\":"+y+"}";
}

/**
 * value item_element object for scatter chart element use for json format 
 * @param y: datavalue
 * @param x: datavalue 
 * @retun object
 */
Feeder.prototype.scatter=function(x, y) {
    var oPoint = {};
    oPoint["x"] = x;
    oPoint["y"] = y;
    return oPoint;
}

/**
 * value item_element object for pie element use for json format 
 * @param y: datavalue
 * @param x: datavalue
 * @retun object
 */
Feeder.prototype.pie=function(x, y) {
    var oPoint = {};
    oPoint["value"] = x;
    oPoint["label"] = y;
    return oPoint;
}

/**
 * get the datavalue of caption of chart from co object
 * @param captionid: excel rangevalue for chart
 * @return caption datavalue
 */ 
Feeder.prototype.getCaption=function(captionid) {
	if(!this.isXLAddress(captionid)){
		return captionid;
	}
    var arrTmp;
    var i = 0;
    for (var indx0 = 0; indx0 < co[captionid].length; indx0++)
        for (var indx1 = 0; indx1 < co[captionid][indx0].length; indx1++)
        arrTmp = (co[captionid][indx0][indx1]);
    return arrTmp;
};

/**
 * get the datavalue of catgegory of chart from co object
 * @param categoryid: excel rangevalue for chart
 * @return categoryid array datavalue
 */ 
Feeder.prototype.getCategory=function(categoryid) {
    var arrTmp = new Array();
    var i = 0;
    for (var indx0 = 0; indx0 < co[categoryid].length; indx0++)
        for (var indx1 = 0; indx1 < co[categoryid][indx0].length; indx1++)
        arrTmp[i++] = (co[categoryid][indx0][indx1]);
    return arrTmp;
}

/**
 *
 * @param sheetid:
 * @param chartid:
 * @param axisid:
 * @param value:
 */
Feeder.prototype.formatvalue=function(sheetid, chartid, axisid, value) {
    var strFormatValue;
    switch (axisid) {
        case 1:
            strFormatValue = "$" + value;
            break;
        case 2:
            strFormatValue = value + "%";
            break;
    }
    return strFormatValue;
}

/**
 *
 * @param xrange:
 * @param yrange:
 * @param refx:
 * @return
 */
Feeder.prototype.getValues=function(xrange, yrange, refx,fmtCode) {
    var arrTmp = new Array();
    var col = new Collection();
    var lenxRange, lenyRange;
    if (xrange.length > 0 && yrange.length > 0) {
		arr0=this.getArray(xrange);
		arr1=this.getArray(yrange);
		var lenArr = arr0.length;
		for(var i=0;i<lenArr;i++)
		{
			col.add(refx(arr0[i],arr1[i]));
		}
    }
    else if (yrange.length > 0) {
		var arr = this.getArray(yrange);
		var lenArr = arr.length;
		for(var i=0;i<lenArr;i++)
		{
			col.add(refx(arr[i],fmtCode));
		}
    }
    else if (xrange.length > 0) {
		var arr = this.getArray(xrange);
		var len = arr.length;
		for(var i=0;i<len;i++)
		{
			col.add(refx(arr[i],fmtCode));
		}
    }
    return col.arr;
}

/**
 * generates the json format string value for the vertical stack bar
 * @param arrRange: array valueRanges
 * @return string json format
 */
Feeder.prototype.getColumnStackValuesData=function(arrRange) {
    var lenParam = arrRange.length;
    var lenRow = co[arrRange[0]].length;
    var lenColumn = co[arrRange[0]][0].length;
    var collValues = new Collection();
    for (var row = 0; row < lenRow; row++)
        for (var column = 0; column < lenColumn; column++) {
        var collItem = new Collection();
        for (var par = 0; par < lenParam; par++) {
            collItem.add(this.tryVerifyData(co[arrRange[par]][row][column]));
        }
        collValues.add(collItem.me())
    }
    return collValues.me();
}

/**
 *generates the json string values for the horizontal stack bar 
 *@param arrRange:  value range array
 *@param nMin: the axis min value
 *@return [[{"left":0,"right":45},{"left":45,"right":110}],[{"left":0,"right":65},{"left":65,"right":87}]]
 */
Feeder.prototype.getBarStackValuesData=function(arrRange,nMin) {
    var lenParam = arrRange.length;
    var lenRow = co[arrRange[0]].length;
    var lenColumn = co[arrRange[0]][0].length;
    var collValues = new Collection();
	for (var par = 0; par < lenParam; par++)
	{
		var collItem = new Collection();
		var nLeft=0;
		var nRight=0;
		var nTemp=nMin;
		for (var row = 0; row < lenRow; row++)
		{
			for (var column = 0; column < lenColumn; column++) 
			{								
				nLeft=nTemp;
				nRight= nMin+co[arrRange[par]][row][column];				
				nTemp=nRight;
				collItem.add(this.stackPoint(nLeft,nRight));				
			}
		}
		collValues.add(collItem.me());
	}
    return collValues.me();
}

/**
 * generates the labels for Radar chart
 * @param categoryid: the excel range addressid for category
 * @param fontSize: fontsize of label 
 * @param bVisible: boolean value indicate for visiblility of label in radar.
 * @return {"labels":[{"text":"Simon","size":"10","visible":true}
 */
Feeder.prototype.genRadarLabels=function(categoryid,fontSize,bVisible){
	var arrTmp = new Array();
	var coll = new Collection();
		var i = 0;
		for(var indx0 = 0; indx0 < co[categoryid].length; indx0++)
			for(var indx1 = 0; indx1 < co[categoryid][indx0].length; indx1++){
				var oLabel = {};
				oLabel["text"]=co[categoryid][indx0][indx1];
				oLabel["size"]=fontSize;
				oLabel["visible"]=bVisible;
				coll.add(oLabel);
			}
		return coll.me();
}

/**
 * generates the object for the element of horizontal bar 
 * @dependency: reference by getBarStackValuesData
 * @param nLeft: number data for the left point
 * @param nRight: number data value for the right point
 * @return object
 */
Feeder.prototype.stackPoint=function(nLeft,nRight){
	var oPoint={};
	oPoint["left"]=nLeft;
	oPoint["right"]=nRight;
	return oPoint;
}

/**
 * searchs the swf object
 * @param movieName: div id name containing the swf.
 * @return
 */
Feeder.prototype.findSWF=function(movieName) {
     if (window.document[movieName]) 
  {
	 return window.document[movieName];
  }
  if (navigator.appName.indexOf("Microsoft Internet")==-1)
  {
	if (document.embeds && document.embeds[movieName]){
	  return document.embeds[movieName]; 
	  }
  }
  else
  {
    return document.getElementById(movieName);
  }
}

/**
 * @Original:ettalk
 * @modified: ShreeBatsa Prajapati
 * @modified: Ramesh Shrestha
 * @Date: 9/24/2009
 * @Description: Generates the min, max and Step Value for the Chart Axis
 * from array of Values.
 * @return 3element array:
 */
var webctrl_trend_format_axis =
{
         max:0, //Highest value of the array
         min:0, //Lowest value of the array   
         ntick:10, //Number of tick marks     
         //Function to calculate the Y-Axis scale for the trend data.         
         y_axis_for_trend : function(trend_array)
         {
         this.max = trend_array[0];
         array_length = trend_array.length;  //Length of the array
         // Calculate the highest trend value.
            for (i = 0; i < array_length; i++)
            {
               if (trend_array[i] >= this.max)
               {
               this.max = trend_array[i];
               }
            }		
            if (this.max == 0)   {this.max = 10;} //If the Trend Array is empty or all values are zero, set the default Max Value to 10
         this.min = this.max;
         // Calculate the lowest trend value.
            for (i = 0; i < (array_length); i++)
            {
               if (trend_array[i] <= this.min)
               {
               this.min = trend_array[i];
               }   
            }            
			if(this.max==this.min){
				this.min=0;
			}
			this.max = this.max+0.05*(this.max-this.min);
			
			if(this.min>0){
				this.min = this.min-0.05*(this.max-this.min);
				if(this.min<0){
					this.min =0;
				}
			}
         //Algorithm to calculate the graph axis tick marks
         range = this.nicenum(this.max - this.min, 'false');
         d = this.nicenum((range) / (this.ntick - 1), 'true');   //Tick mark spacing
         graphmin = Math.floor(this.min / d) * d;            //Graph range min
         graphmax = Math.ceil(this.max / d) * d;            //Graph range max
         nfrac = Math.max( -Math.floor(this.log10(d)),0);

         total = graphmin - d;
         tick_marks = [];
            for (i = 0; total < (graphmax); i++)
            {   
               total = total + d;
               tick_marks[i] = Math.round(total, nfrac);   
            }
         result = [];
         result[0] = graphmin;
         result[1] = graphmax;
         result[2] = d;
         return result;
         },
         
         nicenum : function(x, round1)
         {
         exp = Math.floor(this.log10(x));   //Exponent of X
         f = x / Math.pow(10,exp);      //Fractional part of X
         if (round1)
         {
            if (f < 1.5)   {
               nf = 1;
            } else if (f < 3)   {
               nf = 2;
            } else if (f < 7)   {
               nf = 5;
            } else    {
               nf = 10;   
            }
         } else    {
            if (f <= 1)   {
               nf = 1;
            } else if (f <= 2)   {
               nf = 2;
            } else if (f <= 5)   {
               nf = 5;
            } else    {
               nf = 10;      
            }
         }
         nicenum = nf * Math.pow(10,exp);   
         return nicenum;
         },
		 log10:function(arg) {
			// http://kevin.vanzonneveld.net
			// +   original by: Philip Peterson
			// +   improved by: Onno Marsman
			// +   improved by: Tod Gentille
			// *     example 1: log10(10);
			// *     returns 1: 1
			// *     example 2: log10(1);
			// *     returns 2: 0
			return Math.log(arg)/Math.LN10;
		}
}

/**
 * function to find the max value in given array numbers.
 * @param array: input array of numbers
 * @return max number in array
 */
Feeder.prototype.maxValue = function(array) 
{
	var mxm = array[0];
	for (i=0; i<array.length; i++) 
	{
		if (array[i]>mxm) 
		{
			mxm = array[i];
		}
    }
    return mxm;
};

/**
 * function to find the min value in given array of numbers.
 * @param array: input array of numbers
 * @return min number in array
 */ 
Feeder.prototype.minValue = function(array) 
{
	var mn = array[0];
	for (i=0; i<array.length; i++) 
	{
		if (array[i]<mn) 
		{
			mn = array[i];
		}
	}
return mn;
};

/**
 * generates the min, max number value for the axis in Date case.
 * @param arrRange: the array of ValueRanges
 * @return 3element array:
 */
Feeder.prototype.getDateMinMax = function(arrRange, isStackChart) {
    var arr = new Array();
    //alert("HI");
    var i = 0;
    var lenRange = arrRange.length;
    for (var idxRange = 0; idxRange < lenRange; idxRange++) {
        var lenXRange = co[arrRange[idxRange]].length;
        for (var indx0 = 0; indx0 < lenXRange; indx0++) {
            for (var indx1 = 0; indx1 < co[arrRange[idxRange]][indx0].length; indx1++) {
                arr[i] = co[arrRange[idxRange]][indx0][indx1];
                i++;
            }
        }
        //alert("HI1");
    }
    var arrResult = new Array();
    //if(!isNaN(this.maxValue(arr))
    //if(!isNaN(this.minValue(arr))
    //alert("my dear minvalue: " + this.minValue(arr));
    arrResult[0] = this.minValue(arr);
    arrResult[1] = this.maxValue(arr);
    return arrResult;
}

/**
 * generates the min, max and step for the axis in general case.
 * @param arrRange: the array of ValueRanges
 * @return 3element array:
 * @update: Feb 26 2010
 */
Feeder.prototype.getNormalMinMaxStep=function(arrRange,isHrzBar){

var arr = new Array();
var i=0;
/*if(this.IsConstant(arrRange)){
			arr = this.toArray(arrRange);
	}
	else{*/
var lenRange = arrRange.length;
for(var idxRange = 0; idxRange < lenRange; idxRange++)
{
	if(this.IsConstant(arrRange[idxRange]))
	{
		var arrTmp = this.toArray(arrRange[idxRange]);
		arr = arrTmp;
		i = arrTmp.length;
	}
	else
	{
	 var lenXRange = co[arrRange[idxRange]].length;
		for (var indx0 = 0; indx0 < lenXRange; indx0++)
		{
			var len2Indx = co[arrRange[idxRange]][indx0].length
			for (var indx1 = 0; indx1 < len2Indx; indx1++)
			{
				//col.add(refx(co[xrange][indx0][indx1], co[yrange][indx0][indx1]));
				arr[i] = this.filterNaN(co[arrRange[idxRange]][indx0][indx1]);
				i++;
			}
		}
	}
}
if(isHrzBar){
	arr[i]=0;
}
//}
if(arr.length > 0){
	return webctrl_trend_format_axis.y_axis_for_trend(arr);
	}
}

/**
 * generates the min, max and step for the axis in case of column stack chart
 * @param arrRange: the array of ValueRanges.
 * @return 3element array:
 * @modified: Feb 22 2010
 */
Feeder.prototype.getStackMinMaxStep=function(arrRange)
{
	var arr = new Array();
	var arrElemCountInRanges = new Array();
	var lenRange = arrRange.length;
	for(var idxRange = 0; idxRange < lenRange; idxRange++)
	{
		var lenXRange = co[arrRange[idxRange]].length;
		/*storing the length of each element of array of arrRange.*/
		arrElemCountInRanges[idxRange]=lenXRange;	
	}
	/* getting the max value in the arrElementInRanges*/
	var lenMaxElemCount = arrElemCountInRanges.max(); 
	var indx0 = 0;
	for(indx0 ; indx0 < lenMaxElemCount; indx0++)
	{
		/*Positive summation of value*/
		var nPosSum = 0;
		/*Negative summation of value*/
		var nNegSum = 0;
		for(var idxRange = 0; idxRange < lenRange; idxRange++)
		{
			var len = co[arrRange[idxRange]][indx0].length;
			var coll = new Collection();
			for (var indx1 = 0; indx1 < len; indx1++)
			{
				//var nTemp = co[arrRange[idxRange]][indx0][indx1];
				
				coll.add(co[arrRange[idxRange]][indx0][indx1]);
			}
			
			var nTemp = this.maxValue(coll.me());
			if(nTemp > 0) /*checkin if the value is +ve*/
			{
				nPosSum += nTemp;	
			}
			else if(nTemp < 0) /*checkin if the value if -ve*/
			{
				nNegSum += nTemp;
			}
			
		}
		if(nPosSum >= 0)
			arr[indx0] = nPosSum;
		if(nNegSum < 0)
			arr[indx0] = nNegSum;
	}
	/*this will generate min value, otherwise stack will missleaded to out of axis*/
	arr[++indx0]=0; 
	return webctrl_trend_format_axis.y_axis_for_trend(arr);
}

/**
 * extending Array Object to apply max functionality
 * @created: Feb 22 2010
 */ 
Array.prototype.max = function() {
var max = this[0];
var len = this.length;
for (var i = 1; i < len; i++) if (this[i] > max) max = this[i];
return max;
}

/**
 * extending Array Object to apply min functionality
 * @created: Feb 22 2010
 */ 
Array.prototype.min = function() {
var min = this[0];
var len = this.length;
for (var i = 1; i < len; i++) if (this[i] < min) min = this[i];
return min;
}

/**
 * generates the Radar axis labels
 * @param nMax: max axis label datavalue
 * @param nMin: min axis label datavalue
 * @param nStep: step of axis label value
 * @return the string,javascript string, ["4","34","45","65"]
 */
Feeder.prototype.getRadarAxisLabel=function(nMax,nMin,nStep){
	var collLabel = new Collection();
	if(isFinite(nMax) && isFinite(nMin) && isFinite(nStep)){
		var intFold = nMax/nStep;                 
        for (var i = nMin; i <= intFold; i++)
        {
            collLabel.add(String(i * nStep));
        }
    }
	return collLabel.me();
}

/**
 * filters the NaN value in parameters, returns
 * the same parameter if it's Finite or string value
 * other wise returns zero.
 * @param arg: argument to be check
 * @return the validated value otherwise zero for NaN value.
 */ 
Feeder.prototype.filterNaN = function(arg)
{
	if(isFinite(arg))
	{
		return arg;
	}
	else
	{
		if(typeof(arg) == 'string')
			{
				return arg;	
			}
			else
			{
				return 0;
			}
	}
}
