/*
 * Ping.fm commands for Ubiquity.
 * By Alex McChesney.
 * alex.mcchesney@gmail.com
 * http://ubiquity.washing-up.co.uk/
 * Twitter: alexmcchessers
 */

var Base64 = {

    // private property
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

    // public method for encoding
    encode : function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;

        input = Base64._utf8_encode(input);

        while (i < input.length) {

            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }

            output = output +
            this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
            this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

        }

        return output;
    },

    // public method for decoding
    decode : function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        while (i < input.length) {

            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }

        }

        output = Base64._utf8_decode(output);

        return output;

    },

    // private method for UTF-8 encoding
    _utf8_encode : function (string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }

        return utftext;
    },

    // private method for UTF-8 decoding
    _utf8_decode : function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;

        while ( i < utftext.length ) {

            c = utftext.charCodeAt(i);

            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }

        }

        return string;
    }

}

/* Posts a message via ping.fm */
function ping_fm_post(message, method, title)
{
    // Build parameters for request
    var params = 
    {
       api_key: "f7492d5642382f00f7fa468abef04467",
       user_app_key:Application.prefs.getValue("extensions.ping.fm@washing-up.co.uk.app_key", undefined),
       post_method:"default",
       body:message
    };
    
    if(title!=undefined)
    {
    	params.title=title;
    }
    
    if(method!=undefined)
    {
    	params.post_method = method;
    }

    jQuery.ajax({
      type: "POST",
      dataType: "xml",
      url: "http://api.ping.fm/v1/user.post",
      data: params,
      error: function() 
      {
        displayMessage("Error sending message to Ping.fm");
      },

      success: function(xml) {
        var result = jQuery(xml).find("rsp");
        var code = result.attr("status");
        if (code == "OK") 
        {
          displayMessage("Message sent to Ping.fm.");
        } 
        else 
        {
          var error = jQuery(result).find("message");
          displayMessage("Error sending message to Ping.fm: " + error.text());
        }

      }
    });
}

/* Builds message preview */
function ping_fm_preview(pblock, body, title)
{
	if(title!=undefined)
	{
		pblock.innerHTML = "<p><b>" + title + "</b></p>";
	}
	else
	{
		pblock.innerHTML = "";
	}
	
	pblock.innerHTML += "<p>" + body.text + "</p>";
	     
    pblock.innerHTML+="<p><b>Total characters: " + body.text.length + "</b></p>";
    if (Application.prefs.getValue("extensions.ping.fm@washing-up.co.uk.app_key", undefined)==undefined)
    {
       pblock.innerHTML+="<p><font color='red'>Before you can use this command, you must first call the \"set ping key\" command, passing it your Ping.fm application key.  This will be stored and you will not need to re-enter it unless you switch to a different Ping.fm account.  You can find your application key at <a href='http://ping.fm/key' target='ping'>http://ping.fm/key</a></font></p>";
    }
}

/* Ping to default target */
CmdUtils.CreateCommand({
  names: ["ping"],
  icon: "http://ping.fm/favicon.ico",
  homepage: "http://ubiquity.washing-up.co.uk/",
  author: { name: "Alex McChesney", email: "alex.mcchesney@gmail.com"},
  contributors: ["Alex McChesney"],
  license: "MPL",
  description: "Posts a message using the Ping.fm service.",
  help: "The syntax of the 'ping' command is: ping <i>your message</i></p>",
 
  arguments: [ {role: 'object', nountype: noun_arb_text, label: 'message'} ],

  	preview: function(pblock, args) 
	{
	       ping_fm_preview(pblock, args.object);
	},

	execute: function(args) 
   	{		
		ping_fm_post(args.object.text);	
  	}
})

/* Ping to blog target */
CmdUtils.CreateCommand({
	names: ["ping blog"],
	 icon: "http://ping.fm/favicon.ico",
	 homepage: "http://ubiquity.washing-up.co.uk/",
	 author: { name: "Alex McChesney", email: "alex.mcchesney@gmail.com"},
	 contributors: ["Alex McChesney"],
	 license: "MPL",
	 description: "Posts a message to your configured blogging services using Ping.fm.",
	 help: "The syntax of the 'ping blog' command is: ping blog <i>your message</i> as <i>title</i></p>",
 
	 arguments: [ {role: 'object', nountype: noun_arb_text, label: 'message'},
	              {role: 'alias', nountype: noun_arb_text, label: 'titled'} ],
	

  	preview: function(pblock, args) 
	{
	   ping_fm_preview(pblock, args.object, args.alias.text);
	},

	execute: function(args) 
   	{	
	    ping_fm_post(args.object.text, "blog", args.alias.text);	
  	}
})

/* Ping to microblog target */
CmdUtils.CreateCommand({
	names: ["ping microblog"],
	 icon: "http://ping.fm/favicon.ico",
	 homepage: "http://ubiquity.washing-up.co.uk/",
	 author: { name: "Alex McChesney", email: "alex.mcchesney@gmail.com"},
	 contributors: ["Alex McChesney"],
	 license: "MPL",
	 description: "Posts a message to your configured blogging services using Ping.fm.",
	 help: "The syntax of the 'ping microblog' command is: ping microblog <i>your message</i></p>",
 
	 arguments: [ {role: 'object', nountype: noun_arb_text, label: 'message'}],
	

  	preview: function(pblock, args) 
	{
	   ping_fm_preview(pblock, args.object);
	},

	execute: function(args) 
   	{		
		ping_fm_post(args.object.text, "microblog");	
  	}
})

/* Ping to status target */
CmdUtils.CreateCommand({
	names: ["ping status"],
	 icon: "http://ping.fm/favicon.ico",
	 homepage: "http://ubiquity.washing-up.co.uk/",
	 author: { name: "Alex McChesney", email: "alex.mcchesney@gmail.com"},
	 contributors: ["Alex McChesney"],
	 license: "MPL",
	 description: "Posts a message to your configured blogging services using Ping.fm.",
	 help: "The syntax of the 'ping status' command is: ping status <i>your message</i></p>",
 
	 arguments: [ {role: 'object', nountype: noun_arb_text, label: 'message'}],
	

  	preview: function(pblock, args) 
	{
	   ping_fm_preview(pblock, args.object);
	},

	execute: function(args) 
   	{		
		displayMessage(args.object);
		ping_fm_post(args.object.text, "status");	
  	}
})

CmdUtils.CreateCommand({
	names: ["set ping key"],
  icon: "http://ping.fm/favicon.ico",
  homepage: "http://ubiquity.washing-up.co.uk/",
  author: { name: "Alex McChesney", email: "alex.mcchesney@gmail.com"},
  contributors: ["Alex McChesney"],
  license: "MPL",
  description: "Records your Ping.fm application key to allow other Ping.fm commands to function.  Your application key can be found at <a href='http://ping.fm/key'>http://ping.fm/key</a>",
  help: "The syntax of the 'set ping key' command is: set ping key <i>your app key</i></p>",
 
  arguments: [ {role: 'object', nountype: noun_arb_text, label: 'key'} ],

  	preview: function(pblock, args) 
	{
	   pblock.innerHTML = "<p>This command stores your Ping.fm application key, so that other Ping.fm commands can function.  Your application key can be found at <a href='http://ping.fm/key'>http://ping.fm/key</a></p>";
	},

	execute: function(args) 
   	{		
		if (args.object!=undefined)
        {
           Application.prefs.setValue("extensions.ping.fm@washing-up.co.uk.app_key", args.object.text);
           displayMessage("Ping.fm application key set.");
        }	
  	}
})

CmdUtils.CreateCommand({
	names: ["latest pings"],
  icon: "http://ping.fm/favicon.ico",
  homepage: "http://ubiquity.washing-up.co.uk/",
  author: { name: "Alex McChesney", email: "alex.mcchesney@gmail.com"},
  contributors: ["Alex McChesney"],
  license: "MPL",
  description: "Lists your most recent messages posted to Ping.fm",
 
  _params: function() 
  {      
    var params = 
    {
       api_key: "f7492d5642382f00f7fa468abef04467",
       user_app_key:Application.prefs.getValue("extensions.ping.fm@washing-up.co.uk.app_key", undefined),
       limit:5
    };
    
    return params;
  },


  preview: function(pblock) 
  {
    // No app key?
    if (Application.prefs.getValue("extensions.ping.fm@washing-up.co.uk.app_key", undefined)==undefined)
    {
       pblock.innerHTML="<p><font color='red'>Before you can use this command, you must first call the \"set ping key\" command, passing it your Ping.fm application key.  This will be stored and you will not need to re-enter it unless you switch to a different Ping.fm account.  You can find your application key at <a href='http://ping.fm/key' target='ping'>http://ping.fm/key</a></font></p>";
    }
    else
    {
    	pblock.innerHTML = "";
     	jQuery.ajax({
      	type: "POST",
      	dataType: "xml",
      	url: "http://api.ping.fm/v1/user.latest",
      	data: this._params(),
      	error: function() 
      	{
        	displayMessage("Error requesting posts from Ping.fm");
      	},

      	success: function(xml) 
      	{
        	var result = jQuery(xml).find("rsp");
        	var code = result.attr("status");
        	if (code == "OK") 
        	{
          		var message = jQuery(result).find("message");
          		message.each(function() 
          		{
          			// For each message element in the result, write a div
          			pblock.innerHTML+="<p>";
          			
          			// Title in bold, if any
          			var thisMessage = jQuery(this);
          			var title = thisMessage.find("title");
          			if(title!=undefined && title.text()!="")
          			{
          				pblock.innerHTML+="<b>" + Base64.decode(title.text()) + "</b><br>";
          			}
          			
          			//Actual message content
					var body = thisMessage.find("body");
          			if(body!=undefined)
          			{
          				pblock.innerHTML+=Base64.decode(body.text()) + "<br>";
          			}
          			          			
          			// Service icons
          			var services = thisMessage.find("service");
          			services.each(function()
          			{
          				var thisService = jQuery(this);
          				pblock.innerHTML+="<img src='http://ping.fm/_images/icons/" + thisService.attr("id") + ".png' title='" + thisService.attr("name") + "'/>";
          				pblock.innerHTML+="&nbsp;&nbsp;";
          			});
          			
          			// Posting time
          			var postDate = new Date();
          			postDate.setTime(Date.parse(thisMessage.find("date").attr("rfc")));
          			
          			pblock.innerHTML+="<font size='-1'>" + postDate.toLocaleString() + "</font><br>";
          			
          			pblock.innerHTML+="</p>";
          		});
          		
        	} 
        	else 
        	{
          		var error = jQuery(result).find("message");
          		displayMessage("Error retrieving posts from Ping.fm: " + error.text());
        	}
      	}
      });
  }
  }
})
