var RH = {
};
RH.Util = Class.create();
RH.Util.contextPath = '/';
RH.Util.loadingImage = '/images/common/loadingball.gif';
RH.Util.SECOND_IN_MS = 1000.0;
RH.Util.MINUTE_IN_MS = RH.Util.SECOND_IN_MS*60;
RH.Util.HOUR_IN_MS = RH.Util.MINUTE_IN_MS * 60;
RH.Util.DAY_IN_MS = RH.Util.HOUR_IN_MS * 24;
RH.Util.WEEK_IN_MS = 7 * RH.Util.DAY_IN_MS;
Date.s_users_tz_offset_ms = 0;
Date.prototype.format = function(/** String*/ format) {
  var addZero = function(vNumber){ 
    return ((vNumber < 10) ? "0" : "") + vNumber 
  } 
  var localOffsetMS = new Date(this.getTime()).getTimezoneOffset()*60*1000;
  var tzOffset = this.users_tz_offset_ms ? this.users_tz_offset_ms +localOffsetMS: Date.s_users_tz_offset_ms ? Date.s_users_tz_offset_ms+localOffsetMS : 0; 
  var tzOffsetUsed = this.users_tz_offset_ms ? this.users_tz_offset_ms : Date.s_users_tz_offset_ms;
  var dateAdjusted = new Date(this.getTime() + tzOffset);
    var vDay                      = addZero(dateAdjusted.getDate()); 
    var vMonth            = addZero(dateAdjusted.getMonth()+1); 
    var vYearLong         = addZero(dateAdjusted.getFullYear()); 
    var vYearShort        = addZero(dateAdjusted.getFullYear().toString().substring(3,4)); 
    var vYear             = (format.indexOf("yyyy")>-1?vYearLong:vYearShort) 
    var vHour             = addZero(dateAdjusted.getHours()); 
    var vMinute           = addZero(dateAdjusted.getMinutes()); 
    var vSecond           = addZero(dateAdjusted.getSeconds());
    var vGMT           = "GMT" + (tzOffsetUsed>=0 ? "+" : "-") + Math.abs(Math.round(tzOffsetUsed / 3600 /1000));
    var vDayS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][dateAdjusted.getDay()];
    var vDateString       = format.replace(/dd/g, vDay).replace(/MM/g, vMonth).replace(/y{1,4}/g, vYear).replace(/E{1,3}/g, vDayS);
    vDateString           = vDateString.replace(/HH/g, vHour).replace(/mm/g, vMinute).replace(/ss/g, vSecond);
    vDateString           = vDateString.replace(/Z/g, vGMT);
    return vDateString 
}
Date.prototype.createTZDate = function(dt, offset) {
	dt.offset = offset;
	return dt;
}

Date.prototype.formatSimple = function() {
	if(this.format("yyyy-MM-dd") == new Date().format("yyyy-MM-dd")) {
		return this.format("HH:mm");
	} else {
		return this.format("yyyy-MM-dd HH:mm");
	}
}
Date.prototype.getTimestampStringFromDate = function() {
	return this.format("yyyy-MM-dd HH:mm Z");
}

Date.prototype.getTimestampStringFromDateWithContext = function(/** Date */ context) {
	if(this.format("yyyy-MM-dd") == context.format("yyyy-MM-dd")) {
		return this.format("HH:mm");
	} else {
		return this.format("yyyy-MM-dd HH:mm");
	}
}
Date.prototype.setISO8601 = function (string) {
    var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
        "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
        "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
    var d = string.match(new RegExp(regexp));

    var offset = 0;
    var date = new Date(d[1], 0, 1);

    if (d[3]) { date.setMonth(d[3] - 1); }
    if (d[5]) { date.setDate(d[5]); }
    if (d[7]) { date.setHours(d[7]); }
    if (d[8]) { date.setMinutes(d[8]); }
    if (d[10]) { date.setSeconds(d[10]); }
    if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
    if (d[14]) {
        offset = (Number(d[16]) * 60) + Number(d[17]);
        offset *= ((d[15] == '-') ? 1 : -1);
    }

    offset -= date.getTimezoneOffset();
    time = (Number(date) + (offset * 60 * 1000));
    this.setTime(Number(time));
}
RH.Util.getHumanReadableBandwdithUsage = function(bytes) {
	bytes = new Number(bytes);
	if (bytes < new Number(1024 * 1024)) {
	    return "" + Math.round(bytes / 1024) + " KB";
	}
	if (bytes < new Number(1024 * 1024 * 1024 * 100)) {
	    return "" + Math.round(bytes / 1024 / 1024) + " MB";
	}
	return "" + Math.round(bytes / 1024 / 1024 / 1024) + " GB";
}
RH.Util.getHumanReadableDuration = function(/** long */ originalDurationMS, /** int */ accuracy) {
		var isProperCaseNotLowerCase = true;
        var val = 0;
        var foundMatch = false;
        var result = "" + originalDurationMS + ' ' + (isProperCaseNotLowerCase ? "M" : "m") +"illisecond"
                + (originalDurationMS != 1 ? "s" : "");
        var info = [
                // multiplier, name, cutoff for max value to use unit
                [ 1, (isProperCaseNotLowerCase ? "M" : "m") + "illisecond",
                        RH.Util.SECOND_IN_MS * accuracy , 1],
                [ RH.Util.SECOND_IN_MS, (isProperCaseNotLowerCase ? "S" : "s") + "econd",
                        RH.Util.MINUTE_IN_MS * accuracy , 1],
                [ RH.Util.MINUTE_IN_MS, (isProperCaseNotLowerCase ? "M" : "m") + "inute",
                        RH.Util.HOUR_IN_MS * accuracy , RH.Util.SECOND_IN_MS ],
                // hour
                [ RH.Util.HOUR_IN_MS, (isProperCaseNotLowerCase ? "H" : "h") + "our",
                        RH.Util.DAY_IN_MS * accuracy  , RH.Util.MINUTE_IN_MS],
                // day
                [ RH.Util.DAY_IN_MS, (isProperCaseNotLowerCase ? "D" : "d") + "ay",
                        RH.Util.WEEK_IN_MS * accuracy , RH.Util.MINUTE_IN_MS],
                // week
                [ RH.Util.WEEK_IN_MS, (isProperCaseNotLowerCase ? "W" : "w") + "eek",
                        9999999999 , RH.Util.HOUR_IN_MS] ];
        for (var i = 0; i < info.length; i++) {
            var intervalMS = info[i][0];
            var cutOffMS = info[i][2];
            var toleranceMS = info[i][3];
            var durationMS = Math.round(originalDurationMS / new Number(toleranceMS)) * toleranceMS;
            if ((i == info.length - 1 || Math.abs(durationMS) < cutOffMS) && !foundMatch) {
                val = Math.round(new Number(durationMS) / new Number(intervalMS));
                foundMatch = true;
                result = "" + val + " " + info[i][1]
                        + (val != 1 ? "s" : "");
            }
            // exact multiplier match. e.g. on previous iteration we may have
            // settled on 180 minutes
            // but we'll go for 3 hours in preferences. 181 minutes would stay
            // 181 minutes
            if (Math.round(durationMS / intervalMS) == new Number(durationMS) / new Number(intervalMS)
            		&& durationMS > intervalMS
                    && intervalMS > 1 && durationMS > 0) {
                val = Math.round(new Number(durationMS) / new Number(intervalMS));
                if(val<1 && i>0) {
                	continue;
                }
                result = "" + val + " " + info[i][1]
                        + (val != 1 ? "s" : "");
            }
        }
        return result;
};
RH.DropDownMenus = Class.create();
RH.DropDownMenus.prototype = {
		initialize: function(menuIDs) {
			menuIDs.each(function(id) {
				menuHeader = $('mh'+id);
				if(!menuHeader)
					return;
				menuItems =  $('menuItems'+id);
				if(!menuItems) {
					return;
				}
				positionMenu = function() {
					mh2 = $('mh'+id);
					mi2 = $('menuItems'+id);
					var cumulativeOffset = Element.cumulativeOffset(mh2);
					mi2.style.left = cumulativeOffset.left + "px";
					mi2.style.minWidth = mh2.getWidth()+"px";
					//mi2.style.top = (cumulativeOffset.top+menuHeader.getHeight())  + "px";
				}
				positionMenu();
				//document.observe("dom:loaded",positionMenu);
				Event.observe(window, 'load', positionMenu);
				Event.observe(window, 'resize', positionMenu);
				//<span id='ppicpagetop1' onmouseout="dmTimerOut(); bg_out('ppicpagetop1');" onmouseover="DMenu('picpagetop1'); dmTimerOver(); bg_over('ppicpagetop1');"><a href='/index.jsp'>Home</a></span> |
				mouseOut = function(event) {
					mh2 = $('mh'+id);
					mi2 = $('menuItems'+id);
					var relatedTarget = event.relatedTarget;
					if(relatedTarget) {
						try {
							inHeader = Element.descendantOf(relatedTarget, mh2);
							if(inHeader)
								return;
							inMenuItems = Element.descendantOf(relatedTarget, mi2);
							if(inMenuItems)
								return;
						} catch(e) {
							// firefox throws if you mouse over a textarea/input/select.  permission denied to call method blah
						}
					}
					mh2.removeClassName("menuHeaderHighlighted");
					mi2.removeClassName("menuItemsOpened");
				};
				mouseOver = function(event) {
					mh2 = $('mh'+id);
					mi2 = $('menuItems'+id);
					mh2.addClassName("menuHeaderHighlighted");
					mi2.addClassName("menuItemsOpened");
				};
				Element.observe(menuHeader, 'mouseout', mouseOut);
				Element.observe(menuHeader, 'mouseover', mouseOver);
				Element.observe(menuItems, 'mouseout', mouseOut);
				Element.observe(menuItems, 'mouseover', mouseOver);
			});
		}
};

RH.FormToQueryString = function(element){
	element = $(element);
	if(!element)
		return null;
	var elements = element.getElements();
	var map = $H({});
	for(var i = 0; i<elements.length;i++){
		map.set(elements[i].name,$F(elements[i]));
	}
	
	return map.toQueryString();
}

RH.createDate = function(date_obj){
	var date;
	if(!date_obj) {
	    return null;
	}
	if(date_obj.iso_format){
		
		date = new Date();
		date.setISO8601(date_obj.iso_format);
		if(date_obj.tzOffsetMS){
			date.tz_offset_ms = date_obj.tzOffsetMS;
		}
		return date;
	}
	
	date = new Date(date_obj);
	return date;
}

RH.createISODate = function(date){
	var datestring = new Date();
	datestring.setISO8601(date);
	return datestring;
}