﻿Cv.namespace("Cv.Utils");

Cv.Utils = Class.create({
	initialize: function() {
		
	}
});


//###### TextArea #########################

Cv.Utils.insertTabs = function(n, container) {
	var start = container.selectionStart;
	var end   = container.selectionEnd;
	
	var v = container.value;
	var u = v.substr(0, start);
	for (var i=0; i<n; i++) 
		u += "\t";
	
	u += v.substr(end);
	container.value = u;
	container.selectionStart = start+n;
	container.selectionEnd = start+n;
}

//###### String Extensions ################

String.prototype.endsWith = function(str) {
	 return (this.match(str+"$")==str);
}

String.prototype.startsWith = function(str) {
	return (this.indexOf(str) === 0);
}

String.prototype.replaceAll = function(pattern, replaceWith) {
	return this.replace(new RegExp(pattern,"g"), replaceWith)
}

String.prototype.trim = function () {
    return this.replace(/^\s*/, "").replace(/\s*$/, "");
}

//###### Math ################

Cv.Utils.random = function(min, max) {
	return Math.floor(Math.random() * (max - min + 1) + min);
}

Cv.Utils.randomString = function(length) {
	var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
	var rs = "";
	for (var i = 0; i < length; i++) {
		var rnum = Math.floor(Math.random() * chars.length);
		rs += chars.substring(rnum, rnum + 1);
	}
	return rs;
}



//###### Conversion ################


Cv.Utils.DecToBase36 = function(dec) {
	return dec.toString(36);
}

Cv.Utils.Base36ToDec = function(base36) {
	return parseInt(base36, 36);
}

Cv.Utils.UTF8ToByteArray = function(str) {
    var byteArray = [];
    for (var i = 0; i < str.length; i++)
        if (str.charCodeAt(i) <= 0x7F)
            byteArray.push(str.charCodeAt(i));
        else {
            var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
            for (var j = 0; j < h.length; j++)
                byteArray.push(parseInt(h[j], 16));
        }
    return byteArray;
};

Cv.Utils.byteArrayToUTF8 = function(byteArray) {
    var str = "";
    for (var i = 0; i < byteArray.length; i++)
        str +=  byteArray[i] <= 0x7F?
                byteArray[i] === 0x25 ? "%25" :
                String.fromCharCode(byteArray[i]) :
                "%" + byteArray[i].toString(16).toUpperCase();
    return decodeURIComponent(str);
};

//###### Form ################

Cv.Utils.getSelectedRadio = function(radioGroupName) {
	var o = $$('input[type="radio"][name="' + radioGroupName + '"]').find(function(re) {return re.checked;} );
	if (o)
		return o.value;
	else 
		return null;
}

Cv.Utils.setSelectedRadio = function(radioGroupName, value) {
	$$('input[type="radio"][name="' + radioGroupName + '"]').find(function(re) {return re.value == value;} ).checked = true;
}

//###### DateTime ################

//For formatting and other date functions use prototype-date-extensions.js

//Changes the input date, as well. But the output date is not related to the input date
Cv.Utils.addDays = function(date, days) {
	return new Date(date.setDate(date.getDate() + days));
}

Cv.Utils.addMonths = function(date, months) {
	return new Date(date.setMonth(date.getMonth() + months));
}

Cv.Utils.addMinutes = function(date, minutes) {
	return new Date(date.setMinutes(date.getMinutes() + minutes));
}

//January: month = 1
Cv.Utils.getDaysOfMonth = function(year, month) {
	return new Date(year, month, 0).getDate();
}

Cv.Utils.convertDateTimeFromJson = function(jsonDateTime) {
	return date = eval(jsonDateTime.replace(/\/Date\((-*\d+)\)\//gi, "new Date($1)")); 
}

//Returns the timezone of the current machine in format: +4:00 or -12:00 - only full hours!
//Todo v1.1: add half and quarter hour support
//Usable for BeeTagg Core Statistic Timezone
Cv.Utils.getTimeZone = function() {
	var tz = (-1 * Math.round(new Date().getTimezoneOffset() / 60)) + ":00";
		if (tz.substring(0, 1) != "-")
			tz = "+" + tz;
	
	return tz;
}

//region is US or OTHER
Cv.Utils.toDateTimeFormat = function(date, region) {
	var s = "";
	if (region == "US")
		s = date.getFullYear() + "/" + (date.getMonth()+1) + "/" + date.getDay() + " - " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds(); 
	else
		s = date.getDay() + "." + (date.getMonth()+1) + "." + date.getFullYear() + " - " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds(); 
	return s;
}

Cv.Utils.parseDateToIso8601 = function(str, allDayEvent) {
	var y, m, d, H, M, S;

	//dd-MM-yyyy HH:mm:00
	y = str.substring(6, 10);
	m = str.substring(3, 5) - 1;
	d = str.substring(0, 2);
	H = str.substring(11, 13);
	M = str.substring(14, 16);
	S = 0;
	
	var dt = new Date(y, m, d, H, M, S);
		
	return Cv.Utils.toIso8601(dt, allDayEvent);
}
	
Cv.Utils.toIso8601 = function(dt, allDayEvent) {
	var s = dt.getUTCFullYear() + "" +  Cv.Utils._padzero(dt.getUTCMonth() + 1) + "" + Cv.Utils._padzero(dt.getUTCDate());
	if (!allDayEvent)		
		s += "T" + Cv.Utils._padzero(dt.getUTCHours()) + "" +  Cv.Utils._padzero(dt.getUTCMinutes()) + "00Z";
		
	return s;
}

//Used for .net / MySql (UTC)
Cv.Utils.toIso8601WithDash = function(dt, allDayEvent) {
	var s = dt.getUTCFullYear() + "-" +  Cv.Utils._padzero(dt.getUTCMonth() + 1) + "-" + Cv.Utils._padzero(dt.getUTCDate());
	if (!allDayEvent)		
		s += " " + Cv.Utils._padzero(dt.getUTCHours()) + ":" +  Cv.Utils._padzero(dt.getUTCMinutes()) + ":" + Cv.Utils._padzero(dt.getUTCSeconds());
		
	return s;
}

//Used for .net / MySql (UTC)
Cv.Utils.toIso8601WithDashLocal = function(dt, allDayEvent) {
	var s = dt.getFullYear() + "-" +  Cv.Utils._padzero(dt.getMonth() + 1) + "-" + Cv.Utils._padzero(dt.getDate());
	if (!allDayEvent)		
		s += " " + Cv.Utils._padzero(dt.getHours()) + ":" +  Cv.Utils._padzero(dt.getMinutes()) + ":" + Cv.Utils._padzero(dt.getSeconds());
		
	return s;
}

Cv.Utils._padzero = function(n) {
	return n < 10 ? "0" + n : n;
}

//Use Date.getDay()
Cv.Utils.getDayOfWeek = function(dayOfWeekNumber, shortVersion, language) {
	var supportedLanguages = ["de", "en"];
	var short_en = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
	var short_de = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
	
	var long_en = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
	var long_de = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"];	
	
	if (supportedLanguages.indexOf(language) == -1)
		language = "en";
	
	var s = "";	
	if (shortVersion) {
		s = eval("short_" + language)[dayOfWeekNumber];
	}
	else {
		s = eval("long_" + language)[dayOfWeekNumber];
	}
	return s;
}

//###### Common ################


Cv.Utils.setDeceleratingTimeout = function(callback, opt_FinishedCallback, opt_Scope, opt_Condition, opt_MaxIntervalTime, factor, times) {
	var internalCallback = function(t, counter) {
		return function() {
			if (--t > 0) {
				var c = ++counter * factor;
				
				if (opt_MaxIntervalTime != null && c > opt_MaxIntervalTime)
					c = opt_MaxIntervalTime;	
				
				if (opt_Condition != null && opt_Condition.call(opt_Scope) == false)
					return;
									
				window.setTimeout(internalCallback, c);
				callback.call(opt_Scope)
			}
			else {
				if (opt_FinishedCallback != null)
					opt_FinishedCallback.call(opt_Scope);
			}
		}
	}( times, 0 );
	
	window.setTimeout(internalCallback, factor);
}

Cv.Utils.isNullOrEmpty = function(string) {
	if (typeof(string) == "boolean" && string == false)
		return false;
	
	if (typeof(string) == "object") {
		if (string == null)
			return true;
		else
			return false;
	}
	
	if (typeof(string) == "undefined")
		return true;
	
	if (typeof(string) == null)
		return true;
	
	if (string == null || string == "")
		return true;
	else
		return false;
}

Cv.Utils.formatNumber = function(number, seperatorChar) { //use "," or "'" or " "
	number += "";
	x = number.split(".");
	x1 = x[0];
	x2 = x.length > 1 ? "." + x[1] : "";
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, "$1" + seperatorChar + "$2");
	}
	return x1 + x2;
}

Cv.Utils.isNumber = function(text, integerOnly) {
	var val = integerOnly ? "0123456789" : "0123456789.,";
	var res = true;
	var chr;
	
	if (text === undefined || text === null || text === "" || isNaN(text))
		res = false;
	
	for (i = 0; i < text.length && res == true; i++) { 
		chr = text.charAt(i); 
		if (val.indexOf(chr) == -1) res = false;
	}
	return res;
}

Cv.Utils.containsCharsOnly = function(text, allowedChars) {
	var val = allowedChars;
	var res = true;
	var chr;
	
	for (i = 0; i < text.length && res == true; i++) { 
		chr = text.charAt(i); 
		if (val.indexOf(chr) == -1) res = false;
	}
	return res;
}

Cv.Utils.getQueryString = function(key) {
	try {
		var arr = window.location.search.substring(1).split("&");
		for (i = 0; i < arr.length; i++) {
			var arr2 = arr[i].split("=");
			if (arr2[0] == key) return arr2[1];
		}
		return "";
	}
	catch (e) {
		return "";
	}	
}

Cv.Utils.isSpecAscii = function(text) {
	for (var i = 0; i < text.length; i++) {
		asciiNum = text.charCodeAt(i);
		if (asciiNum > 31 && asciiNum < 127) {
			//do nothing			
		} 
		else {
			return false;
		} 
	}
	return true;
}

Cv.Utils.emptyStringForNull = function(text, urlEncode) {
	if (text == null || text == "null") return "";
	return text;	
}

Cv.Utils.renderSpecAscii = function(shortVersion) {
	var s = "";
	for (var i = 32; i < 128; i++) {
		if (!shortVersion || (i < 47 || (i > 57 && i < 65) || (i > 90 && i < 97) || i > 122)) {
			s += String.fromCharCode(i) + " ";
		}
	}
	if (shortVersion) s = "<b>A-Z</b> or <b>a-z</b> or <b>0-9</b> or <b>" + s + "</b>";
	return s;
}


//###### Xml ################

Cv.Utils.xmlStringToXmlDOM = function(string) {
	var xmlDoc;
	if (window.DOMParser) {
		parser = new DOMParser();
		xmlDoc = parser.parseFromString(string,"text/xml");
	}
	else // Internet Explorer
	{			
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async = "false";
		xmlDoc.loadXML(string); 
	}
	return xmlDoc;
}

Cv.Utils.xmlDOMToString = function(xmlDom) {
	if (window.XMLSerializer)
		return (new XMLSerializer()).serializeToString(xmlDom);
	else {
		if (xmlDom.xml)
			return xmlDom.xml;
		else
			alert("This browser is not supported.");
	}
}

//###### Cookie ################

Cv.Utils.Cookie = Class.create({
	initialize: function() {
		
	}
});

/**
 * Sets a cookie. set opt_expiredays to NULL for session cookies.
 * @param {string} name cookie key.
 * @param {string} value cookie value
 * @param {integer?} opt_expiredays Amount of days to save the cookie. Set to NULL for session cookie. Set to -1 (with value == null or "") to delete cookie.
 */	
Cv.Utils.Cookie.setCookie = function(name, value, opt_expiredays) {
	if (opt_expiredays) {
		var date = new Date();
		date.setTime(date.getTime()+(opt_expiredays*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else 
		var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

Cv.Utils.Cookie.getCookie = function(name) {
	if (document.cookie.length > 0) {
		start = document.cookie.indexOf(name + "=");
		if (start != -1) { 
			start = start + name.length + 1; 
			end = document.cookie.indexOf(";", start);
			if (end == -1) end = document.cookie.length;
			return unescape(document.cookie.substring(start, end));
		} 
	}
	return "";
}


//###### Events ################
/*
When and how to use this beast :)
- in case of MULTIPLE elements (differentiated through an ID: e.g: linkBox_123123), that have typically a "click", "onmouseover" or "onmouseout" event registered 
and contain child elements (NESTED), that bubble the event, so the id (123123) of the element is not directly retrievable.
Example:
<div id="box_12" class="classA classB">
	Hello<br /><img id="myPic" src="img.png" />
</div>

if a onmouseover event is registered for box_12, it will trigger, but the actual returned id "myPic".

In order to get the correct id "12", you can us the below function like this (where e is in the signature of the callback function):

Cv.Utils.getIdFromNestedElement(e, "box_", ".classA");  //Do not forget the "." -> it's a selector, not a class name.
*/

Cv.Utils.getIdFromNestedElement = function(e, idPrefix, targetSelector) {
	var id = null;
	if ($(Event.element(e)).id == null || $(Event.element(e)).id == "") {
		if ($(Event.element(e)).up(targetSelector) != null)
			id = $(Event.element(e)).up(targetSelector).id.replace(idPrefix, "");
	}
	else {
		if ($(Event.element(e)).id.startsWith(idPrefix))
			id = $(Event.element(e)).id.replace(idPrefix, "");
		else {
			if ($(Event.element(e)).up(targetSelector) != null)
				id = $(Event.element(e)).up(targetSelector).id.replace(idPrefix, "");
		}			
	}	
	return id;	
}

Cv.Utils.isEventSupported = function(eventName) {
    var TAGNAMES = {
      'select':'input','change':'input',
      'submit':'form','reset':'form',
      'error':'img','load':'img','abort':'img'
    }
    
	var el = document.createElement(TAGNAMES[eventName] || "div");
    eventName = "on" + eventName;
    var isSupported = (eventName in el);
    if (!isSupported) {
		el.setAttribute(eventName, "return;");
        isSupported = typeof el[eventName] == "function";
    }
    el = null;
    return isSupported;
}


//###### Resource ################

Cv.Utils.Resource = Class.create({
	initialize: function() {
		
	}
});

//E.g. Cv.Utils.Resource.getResource("key1", ["Argument1"]); --> args is optional
Cv.Utils.Resource.getResource = function(key, args) {
	var s = key;
	try {
		s = eval(key);
		
		if (args) {
			for (var i = 0; i < args.length; i++) {
				var re = new RegExp("\\{" + i + "\\}", "g");
				s = s.replace(re, args[i]);
			}
		}
	}
	catch (e) {}
	return s;
}


//###### UI ################

Cv.Utils.Wait = Class.create({
	initialize: function() {
		
	}
});

Cv.Utils.Wait.showInContainer = function(id, containerObj) {
	if (containerObj) 
		containerObj.innerHTML = "<img id=\"" + id + "\" src=\"/media/imgs/wait.gif\" />";
}

Cv.Utils.Wait.render = function() {
	return "<img src=\"/media/imgs/wait.gif\" />";
}

Cv.Utils.Wait.renderPath = function() {
	return "/media/imgs/wait.gif";
}

Cv.Utils.Wait.showXY = function() {
	
}

Cv.Utils.Wait.hide = function(id) {
	if ($(id)) $(id).parentNode.removeChild($(id));
}	


//###### Tagging ################

Cv.Utils.Tagging = Class.create({
	initialize: function() {
		
	}
});

Cv.Utils.Tagging.ConvertCodeSystemInt2String = function(intCS) {
	if (intCS == 1)
		return "Honeycomb";
	if (intCS == 2)
		return "Datamatrix";
	if (intCS == 3)
		return "QRCode";
}

Cv.Utils.Tagging.ConvertCodeSystemString2Int = function(stringCS) {
	if (stringCS == "Honeycomb")
		return 1;
	if (stringCS == "Datamatrix")
		return 2;
	if (stringCS == "QRCode")
		return 3;
}

//##### Security ################

Cv.Utils.RSAEncrypt = function(value, exponent, modulus) {
	setMaxDigits(131);
	var key = new RSAKeyPair(exponent, "", modulus);
	var enc = encryptedString(key, value);
	return enc;
}

Cv.Utils.XOR = function(pass, txt) {
 var ord = []
    var buf = ""

    for (z = 1; z <= 255; z++) {ord[String.fromCharCode(z)] = z}

    for (j = z = 0; z < txt.length; z++) {
        buf += String.fromCharCode(ord[txt.substr(z, 1)] ^ ord[pass.substr(j, 1)])
        j = (j < pass.length) ? j + 1 : 0
    }

    return buf
}


