/* -----------------------------------------------------------------------------------------
 * CONFIGURATION
 * ----------------------------------------------------------------------------------------- */


var WshShell = WScript.CreateObject("WScript.Shell");
var tempdir = WshShell.ExpandEnvironmentStrings("%TEMP%") + "\\";
// var tempdir = 'C:/Users/dtc80000160/AppData/Local/Temp/'; // must have write access
var twitter_username = 'thinkstorm';
var skype_username = 'tc_detecon';
var interval = 10 * (60*1000);  // 10 minutes
var executeOnlyOnce = false;

/* -----------------------------------------------------------------------------------------
 * DON'T TOUCH BELOW THIS POINT
 * ----------------------------------------------------------------------------------------- */

WScript.Echo("\n\n\n------------------------------------------------------------------------------");
WScript.Echo("       ---> Update Skype Mood Text From Twitter <---\n");
WScript.Echo("       Skype Username: " + skype_username);
WScript.Echo("       Twitter Username: " + twitter_username);
WScript.Echo("       Temp Directory: " + tempdir);
if (executeOnlyOnce) {
	WScript.Echo("       Execute Once.");
} else {
	WScript.Echo("       Execute every " + interval + " milliseconds.");
}
WScript.Echo("---------------------------------------------------------------------------\n\n");

// helper variables
var dateObj;
var twitterpath = 'http://twitter.com/statuses/user_timeline/' + twitter_username + '.json?count=1';
var richMoodTextFilename = "richMoodText.txt";
var twitterjson_filename = "twitter.json";
var lastRichMoodText = '';

// start skype
var skype = newComObject("Skype4Com.Skype");
if(!skype.Client.IsRunning) skype.Client.Start();

// create Internet Explorer webclient
var ua = createUserAgent();
if (!ua) {
	throw "### ERROR: cannot create Internet Explorer user agent!";
}

// add this line to at least access Skype client once
skype.Attach();

// get current mood message - but make sure the right user is signed on
try {
	lastRichMoodText = getRichMoodTextFromSkype();
} catch (e) {
	print('### ERROR ' + e.number + ': "' + trim(e.description) + '"!');
}

// Create FileSystemObject
var objFSO = WScript.CreateObject("Scripting.FileSystemObject");
var objFile;
var newRichMoodText;

// sleep for some time.  When wakeup, get the twitter status message.
do {
	try {
		if ((newRichMoodText = getTwitterStatus()) || (newRichMoodText = getRichMoodTextFromFile())) {
			updateSkypeRichMoodText(newRichMoodText);
		}
	} catch (e) {
		print('### ERROR (loop): ' + e.number + ': "' + trim(e.description) + '"!');
	}
	if (!executeOnlyOnce) {
		WScript.Sleep(interval);
	}
} while (!executeOnlyOnce);

/* -----------------------------------------------------------------------------------------
 * Actual Work
* ----------------------------------------------------------------------------------------- */


function decodeTwitterResponse(responseText) {
	var moodTextFileName;
	try {
		twitterResponse = eval('(' + responseText + ')');
	} catch (e) {
		print('! WARNING (decodeTwitterResponse): Cannot interpret twitter\'s JSON (' + e.number + ': "' + trim(e.description) + '").');
		return false;
	}
	if (twitterResponse && twitterResponse[0] && twitterResponse[0].text) {
		lastTwitterMessage =  createURLs(trim(twitterResponse[0].text));
		if (!lastTwitterMessage) {
			print('! ABORT (decodeTwitterResponse): last tweet is empty!');
			return false;
		}
		moodTextFileName = tempdir + richMoodTextFilename;
		objFile = objFSO.OpenTextFile(moodTextFileName, 2, true);
		if (!objFile) throw 'cannot open or create "' + moodTextFileName + '" for writing!';
		try {
			objFile.Write(escape(lastTwitterMessage));
			objFile.Close(); 
			return lastTwitterMessage;
		} catch (e) {
			print('! WARNING (decodeTwitterResponse): Cannot write to MoodTextFile (' + e.number + ': "' + trim(e.description) + '").');
			return false;
		}
	}
	print('! WARNING (decodeTwitterResponse): Cannot traverse Twitter\'s JSON.');
	return false;
}

function getTwitterStatus() {
	// return false; // uncomment this for file reading testing
	var twitterResponse;
	var lastTwitterMessage;
	if(skype.CurrentUserHandle!=skype_username) {
		print('! ABORT (getTwitterStatus): current signed-on user is "' + skype.CurrentUserHandle + '", and not "' + skype_username + '".');
		return false;
	}
	try {
		// see http://msdn.microsoft.com/en-us/library/ms759148(VS.85).aspx
		if (ua) {
			print('CONTACTING ' + twitterpath);
			ua.open('GET',twitterpath,false);
			ua.send(null);
			if (ua.status == 200) {
				return decodeTwitterResponse(ua.responseText);
			} else {
				print('! WARNING (getTwitterStatus): Cannot retrieve Twitter data (' + ua.status+ ': "' + trim(ua.responseText) + '").');
				return false;
			}
		} else {
			print('### ERROR (getTwitterStatus): XMLHTTP user agent unexpectedly ended!');
			return false;
		} 
		
	} catch (e) {
		print('### ERROR (getTwitterStatus): ' + e.number + ': "' + trim(e.description) + '"!');
		return false;
	}
}

function getRichMoodTextFromSkype() {
	if(skype.CurrentUserHandle!=skype_username) {
		print('! ABORT (getRichMoodTextFromSkype): current signed-on user is "' + skype.CurrentUserHandle + '", and not "' + skype_username + '".');
		return false;
	}
	return trim(skype.currentUserProfile.RichMoodText);
}

function getRichMoodTextFromFile() {
	var moodText;
	var moodTextFileName;
	try {
		moodTextFileName = tempdir + richMoodTextFilename;
		if(!objFSO.FileExists(moodTextFileName)) { // ups, the file doesn't exist!
			print('! ABORT (getRichMoodTextFromFile): there is no file "' + moodTextFileName + '".');
			return false;
		}
		objFile = objFSO.OpenTextFile(moodTextFileName, 1);
		if  (objFile.Length == objFile.Position)  { // ups, the file is empty!
			print('! ABORT  (getRichMoodTextFromFile, reading file): File "' + moodTextFileName + '" is empty!');
			return false;
		}
		try {
			moodText = trim(objFile.readAll());
			objFile.Close();
			return moodText;
		} catch (e) { // something happened during he readAll() function
			print('### ERROR (getRichMoodTextFromFile, reading file): ' + e.number + ': "' + trim(e.description) + '"!');
			if (objFile) objFile.Close();
			return false;
		}
	} catch (e) { // ups, this was unexpected!
		print('### ERROR (getRichMoodTextFromFile): ' + e.number + ': "' + trim(e.description) + '"!');
		return false;
	}
}

function updateSkypeRichMoodText(text) {
	var currentRichMoodText;
	try {
		if (currentRichMoodText = getRichMoodTextFromSkype()) {
			if (currentRichMoodText != text) {
				skype.currentUserProfile.RichMoodText = text;
				lastRichMoodText = text;
				print('NEW TEXT: ' + text);
			} else {
				print('(no new text)');
			}
		}
	} catch (e) {
		print('### ERROR (updateSkypeRichMoodText): ' + e.number + ': "' + trim(e.description) + '"!');
	}
}

/* -----------------------------------------------------------------------------------------
 * HELPER FUNCTIONS
 * ----------------------------------------------------------------------------------------- */

function createUserAgent () {
    try{
        return new ActiveXObject('Msxml2.XMLHTTP');
    }
    catch (e) {
        try{
            return new ActiveXObject('Microsoft.XMLHTTP');
        }
        catch(e){
            return null;
        }
    }
}

function newComObject (lib) {
    var obj;

    try {
        obj = WScript.CreateObject(lib);
    }
	catch(e){
        obj = new ActiveXObject(lib);
    }

    return obj;
}

function print (string) {
	objDate = new Date();
    WScript.Echo(objDate.toLocaleString() + ": " + trim(string));
}

function trim(text) {
    // Use a regular expression to replace leading and trailing 
    // spaces with the empty string
	var newText;
	var pattern;
	try {
		if (text) {
			pattern = /(^[\s\n\r]*)|([\s\n\r]*$)/g;
			newText = text.replace(pattern, '');
			if (!newText) throw 'error trimming "' + text + '": result is empty.';
			return newText;
		} else {
			return text;
		}
	} catch (e) {
		print('### ERROR (trim): ' + e.number + ': "' + trim(e.description) + '"!');
		return text;
	}		
}

function createURLs(text) {
	var newText;
	var pattern;
	try {
		if (text) {
			newText = text;
			pattern = /(ftp|http|https|file):\/\/[\S]+(\b|$)/gim;
			newText = text.replace(pattern, '<a href="$&">$&</a>');
			if (!newText) throw 'error createURLs for "' + text + '": result is empty.';
			text = newText;
			pattern = /([^\/])(www[\S]+(\b|$))/gim;
			newText = text.replace(pattern, '$1<a href="http://$2">$2</a>');
			if (!newText) throw 'error createURLs for "' + text + '": result is empty.';
			return newText
		} else {
			return text;
		}
	} catch (e) {
		print('### ERROR (createURLs): ' + e.number + ': "' + trim(e.description) + '"!');
		return text;
	}
} 

