/* UTILS (global) */


// PROTOTYPES

// from http://snipplr.com/view/8423/left-pad-string/#comment
// String.prototype.padleft = function (l, c) { return new Array(l - this.length + 1).join(c || '0') + this; }
// String.prototype.padleft = function (l, c) { return this; }

function padleft (s,l,c) { 
	return new Array(l - s.length + 1).join(c || '0') + s ; 
}

// from http://www.somacon.com/p355.php
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g,""); }

// ehm derivation of above trim
// String.prototype.ltrim = function() { return this.replace(/^\s+/g,""); }
// String.prototype.rtrim = function() { return this.replace(/\s+$/g,""); }



// GLOBAL FUNCTIONS

function consolelog (foo) {
	// if (location.href.indexOf('nirvanahq.com') == -1) {
	// 	if (typeof console == "object") {
	// 		console.debug(foo);
	// 	}
	// }
}

// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
// answered Aug 24 '09 at 16:12 Mathieu Pagé -- This create version 4 UUID (created from pseudo random numbers) 
function uuid()
{
   var chars = '0123456789abcdef'.split('');
   var uuid = [], rnd = Math.random, r;
   uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
   uuid[14] = '4'; // version 4
   for (var i = 0; i < 36; i++)
   {
      if (!uuid[i])
      {
         r = 0 | rnd()*16;
         uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
      }
   }
   return uuid.join('');
}

function in_array (s_needle,a_haystack) {
	for (var i in a_haystack) {
		if (a_haystack[i] == s_needle) {
			return true;
		}
	}
	return false;
}

function array_remove (a_haystack,s_needle) {
	for (var i in a_haystack) {
		if (a_haystack[i] == s_needle) {
			delete a_haystack[i];
		}
	}
	return a_haystack;
}

function count (object) {
	var count = 0;
	for (var i in object) {
		count++;
	}
	return count;
}

function strinstr (s_needle,s_haystack) {
	return (s_haystack.indexOf(s_needle) == -1) ? false : true;
}

function dec2hex(d) {
	// based on http://javascript.about.com/library/blh2d.htm
	return Number(d).toString(16);
}

function hex2dec(h) {
	// based on http://javascript.about.com/library/blh2d.htm
	return parseInt(h,16);
}

function time() {
	var oDate = new Date();
	var unixtime = oDate.getTime() / 1000; // fyi: Date.getTime returns microseconds!
	return Math.floor(unixtime);
}

function today() {
	var oDate = new Date();
	var yyyy =  '' + oDate.getFullYear();
	var mm = '' + (oDate.getMonth() + 1);
	var dd = '' + oDate.getDate();
	mm = (mm < 10) ? ''+'0'+mm : ''+mm; // pad left with 0
	dd = (dd < 10) ? ''+'0'+dd : ''+dd; // pad left with 0
	return ''+yyyy+mm+dd;
}

function gmtoffset() {
	// courtesy http://www.24hourapps.com/2009/03/javascript-gmtutc-timezone-offset.html
	var today = new Date();  
	var offset = -(today.getTimezoneOffset()/60); 
	return offset;
}

function energy(minutes) {
	var mh;
	if (minutes == 0) mh = '';
	else if (minutes < 60) mh = minutes + 'm';
	else if (minutes % 30 == 0) mh = (minutes / 30 / 2) + 'h';
	else mh = minutes + 'm';
	return mh;
}

function timetostr(unixtime) {
	var microtime = unixtime * 1000; 
	var date = new Date();
	date.setTime(microtime);
	var yyyy = date.getFullYear();
	var mm = date.getMonth() + 1;
	var dd = date.getDate();
	mm = (mm < 10) ? ''+'0'+mm : ''+mm; // pad left with 0
	dd = (dd < 10) ? ''+'0'+dd : ''+dd; // pad left with 0
	var str = (yyyy < 2000) ? '' : ''+mm+'/'+dd+'/'+yyyy;
	return str;
}

function yyyymmddtostr(yyyymmdd) {
	yyyymmdd = '' + yyyymmdd;  // coerce to string
	if (yyyymmdd == '') {
		return '';
	}
	else {
		var yyyy = '' + yyyymmdd.substr(0,4);
		var mm = '' + yyyymmdd.substr(4,2);
		var dd = '' + yyyymmdd.substr(6,2);
		return '' + mm + '/' + dd + '/' + yyyy;
	}
}

function yyyymmddtounixtime(yyyymmdd) {
	yyyymmdd = '' + yyyymmdd;  // coerce to string
	if (yyyymmdd == '') {
		return 0;
	}
	else {
		var yyyy = '' + yyyymmdd.substr(0,4);
		var mm = '' + yyyymmdd.substr(4,2);
		var dd = '' + yyyymmdd.substr(6,2);
		var oDate = new Date(yyyymmddtostr(yyyymmdd));
		return oDate.getTime() / 1000;
	}
}

function phpdate(format, timestamp) {
	var date = new Date();
	date.setTime(timestamp*1000);
	return $.PHPDate(format,date);
}

function startinForUnixtime(timestamp) {
	var out = {};
	if (timestamp != '') {
		out.days = phpdate('M j',timestamp);
		out.classname = 'scheduled';
	}
	else {
		out.days = 'schedule';
		out.classname = 'nostartdate';
	}
	return out;
}

function dueinForUnixtime(timestamp) {
	var out = {};
	var duein = '';
	var dueinbg = '';
	var dueinxdays = Math.floor((time()-timestamp)/86400);
	out.days = '';
	out.classname = '';
	if (timestamp > 0) {
		if (dueinxdays <= -7 ) { 
			out.days = phpdate('M j',timestamp);
			out.classname = 'duein';
		}
		else if (dueinxdays <= -2 ) {
			out.days = 'due in '+ (-1*dueinxdays) +' days';
			out.classname = 'duein';
		}
		else if (dueinxdays == -1 ) {
			out.days = 'due tomorrow';
			out.classname = 'duein';
		}
		else if (dueinxdays == 0 ) {
			out.days = 'due today';
			out.classname = 'duetoday';
		}
		else if (dueinxdays == 1 ) {
			out.days = '1 day late';
			out.classname = 'overdue';
		}
		else if (dueinxdays >= 2 ) {
			out.days = dueinxdays + ' days late';
			out.classname = 'overdue';
		}
	}
	else {
		out.days = 'due date';
		out.classname = 'noduedate';
	}
	return out;
}

function nl2space (thestring) {
	return thestring.replace(/\n/g," ");
} 

function nl2spacebr (thestring) {
	return thestring.replace(/\n/g," <br>");
} 

function nl2spacebrspace (thestring) {
	return thestring.replace(/\n/g," <br> ");
} 

function nl2br (thestring) {
	return thestring.replace(/\n/g,"<br>");
} 

function br2nl (thestring) {
	return thestring.replace(/<br>/ig,"\n");
} 

function htmlspecialchars (thestring) {
	thestring = thestring.replace(/&/g,"&amp;");
	thestring = thestring.replace(/</g,"&lt;");
	thestring = thestring.replace(/>/g,"&gt;");
	thestring = thestring.replace(/"/g,"&quot;");
	return thestring;
} 

function linkit (thestring,mailto) {
	var linkmailto = (mailto == false) ? false : true;
	thestring = thestring.replace(/(https:\/\/\S+)/, "<a href='$1' class='nosave' target='_blank'>$1</a>")
	thestring = thestring.replace(/(http:\/\/\S+)/, "<a href='$1' class='nosave' target='_blank'>$1</a>")
	// thestring = thestring.replace(/(ftps:\/\/\S+)/, "<a href='$1' class='nosave' target='_blank'>$1</a>")
	// thestring = thestring.replace(/(ftp:\/\/\S+)/, "<a href='$1' class='nosave' target='_blank'>$1</a>")
	if (linkmailto==true) {
		thestring = thestring.replace(/(\S+@\S+)/, "<a href='mailto:$1' class='nosave'>$1</a> ")
	}
	return thestring;
}

function linkr (thestring,mailto) {
	var lines = thestring.split("\n");
	var words = [];
	var l = 0;
	var w = 0;
	for (l in lines) {
		words = lines[l].split(' ');
		for (w in words) {
			words[w] = linkit(words[w],mailto);
		}
		lines[l] = words.join(' ');
	}
	return lines.join("\n");
}

function subtaskr (thestring) {
	var lines = thestring.trim().split("\n");
	for (var l in lines) {
		lines[l] = lines[l].trim();
		if (lines[l].slice(0,2) == '- ') {
			lines[l] = lines[l].replace('- ','<span class="nosave subtask"><span>-</span></span> ');
		}
		if (lines[l].slice(0,2) == 'x ') {
			lines[l] = lines[l].replace('x ','<span class="nosave subtask checked"><span>x</span></span> ');
		}
	}
	return lines.join("\n");
}

function unsubtaskr (thestring) {
	// var lines = thestring.split("<br>");
	// return lines.join("\n");
	return br2nl(thestring);
}

function inspect(obj) {
   var propList = "";
   for(var propName in obj) {
      if(typeof(obj[propName]) != "undefined") {
         propList += (propName + ': ' + obj[propName] + ",\n");
      }
   }
	return propList;
}

// from http://stackoverflow.com/questions/122102/what-is-the-most-efficent-way-to-clone-a-javascript-object/1891377#1891377
function cloneObject(obj) {
    var clone = {};
    for(var i in obj) {
        if(typeof(obj[i])=="object")
            clone[i] = cloneObject(obj[i]);
        else
            clone[i] = obj[i];
    }
    return clone;
}

function sortEntitiesBy (entities, column, ascdesc, numeric) {

	ascdesc = (ascdesc == 'desc') ? 'desc' : 'asc';
	numeric = (numeric == true) ? true : false;

	var oentities = {}; // entities --> converted to object / collection with entityid as key
	var rentities = {}; // entities --> sorted, to be returned by this method / function, incremented 0-n
	var entity = {}; // temp entity holder

	for (var i in entities) {
		entity = entities[i];
		oentities[entity.id] = entity;
	}

	var column_entityid = []; // to hold concat: column | entityid, for array sort by string comparison
	if (numeric) {
		for (var i in oentities) {
			// column_entityid.push(oentities[i][column].padleft(11) + '_' + oentities[i]['id']);
			column_entityid.push(padleft(oentities[i][column],11) + '_' + oentities[i]['id']);
		}
	}
	else {
		for (var i in oentities) {
			column_entityid.push(oentities[i][column].toUpperCase() + '_' + oentities[i]['id']);
		}
	}
	column_entityid.sort(); // in place sort, ascending

	if (ascdesc == 'desc') {
		column_entityid.reverse(); // in place sort, descending
	}
	
	var exploded = [];
	var entityid = 0;
	for (i=0; i<column_entityid.length; i++) {
		exploded = column_entityid[i].split('_'); 
		entityid = parseInt(exploded[1],10); // kills left padded zeros
		if (oentities[entityid] != undefined) {
			rentities[i] = oentities[entityid];
		}
	}

	return rentities;
}

/**
 * this function should be an exact replica of /helpers/nirvana_helper.php :: sanitize_tags() 
 * ensure sure that if one is changed, the other is changed to match
 */
function sanitizeTags(s_tags) {
	if (s_tags != undefined) {
		s_tags = s_tags.trim();
		s_tags = s_tags.toLowerCase();
		s_tags = s_tags.replace(/,/g,' ');
		a_tags = s_tags.split(' ');
		// a_tags = a_tags.sort();
		s_tags = ' ';
		for (var i in a_tags) {
			if (!stristr(s_tags,' '+a_tags[i]+' ')) {
				s_tags += a_tags[i] + ' ';
			}
		}
		s_tags = s_tags.trim();
	}
	return s_tags;
}
