      (function($) {
	  // private methods
	  var userName = null;
	  var sess     = null;

	  // get random number
	  function getRandom() {
	      var s = '';
	      for(var i = 0; i < 10; i++) {
		  s = s + Math.floor(Math.random()*9+1);
	      }
	      return s;
	  }


	  // insert new lines
          function insertLines(container, lines) {
              $.map(lines, function(n, i) {
		  var msg = '';
		  var func = $.fn.transmission.display[n[0]];

		  if(func) {
		      msg = func(n);
		      $("#output", container).append(msg);
		  }
              });

              $("#output", container).attr({ scrollTop: $("#output", container).attr("scrollHeight") });
          }

	  // - should put POST instead of GET
	  // - remove session
	  function validateAuthentication(container) {
	      $.post($.fn.transmission.defaults["urlTWiki"],
			{"session": sess},
			function(data, textStatus) {
			    initConnection(container);
			}, "json");
	  }
	  
	  function initConnection(container) {
	      $.post($.fn.transmission.defaults["urlBase"],  
			{"method": "init",
			 "session": sess
			},
			function(data, textStatus) {
			    if(data.result) {
				if(data.validate) {
				    validateAuthentication(container);
				} else {
				    userName = data.username;
				    initTransmission(container, data.lines);
				}
			    }
			}, "json");
	  }

	  function initTransmission(container, lines) {
	      container.html($.fn.transmission.skins[$.fn.transmission.defaults["skin"]](container));

	      // show username
	      $("#username").html(userName);
	      // show previous lines
	      insertLines(container, lines);

	      // bind the events
	      $("FORM", container).submit(function() {
		  var txt = $("#input", container).val();

		  $("#input", container).val("");

		  //$("#input", container).attr("disabled", true);
		  $("#input", container).addClass("sending");

		  // throw this in the function
		  $.post($.fn.transmission.defaults["urlBase"],
                            {"method": "send",
			     "session": sess,
                             "type": "message",
                             "value": txt},
                            function(data, textStatus) {
				// $("#input", container).attr("disabled", false);
				$("#input", container).removeClass("sending");
                            }, "json");
	      });
	      
	      // timer
	      setInterval(function() {
		  $.post($.fn.transmission.defaults["urlBase"],
			    {"method": "sync",
			     "session": sess},
			    function(data, textStatus) {
				insertLines(container, data.lines);
			    }, "json");
	      }, $.fn.transmission.defaults["delay"]);
	  }
	  
	  // public methods
	  $.fn.transmission = function(options) {
	      var o = $.extend({}, $.fn.transmission.defaults, options);

	      // get session
	      sess = getRandom();


	      return this.each(function() {
		  var $this = $(this);

		  // show init message
		  $this.html($.fn.transmission.skins["initializing"]($this));

		  // do init
		  initConnection($this);
	      });

	  }

	  // skins
	  $.fn.transmission.skins = {
	      'initializing': function(container) {
		  return "Initializing transmission.";
	      },
	      
	      'small': function(container) {
		  var s = '';
		  s += '<form  enctype="multipart/form-data" onsubmit="javascript: return false">';
		  s += '<table border="0">';
		  s += '<tr><td ><div style="float: right" id="username"></div><b>FM TX</b></td></tr>';
		  s += '<tr><td>';
		  s += '<div id="output"></div>';
		  s += '</td></tr>';
		  s += '<tr><td>';
		  s += '<input type="text" id="input"/>';
		  s += '</td></tr>';
		  s += '<tr><td><i>this chat connects to:<br> irc.freenode.net<br> #flossmanuals </td></tr>';
		  s += '</table>';
		  s += '</form>';
		  
		  return s;
	      }
	  }

	  $.fn.transmission.display = {
	      'msg': function(n) {
		  return '<p><b>'+n[1]+':</b> '+n[2]+'</p>';
	      },

	      'join': function(n) {
		  return '<p><i>'+n[1]+' joined the channel.</i></p>';
	      },

	      'left': function(n) {
		  return '<p><i>'+n[1]+' left the channel.</i></p>';
	      },

	      'edit': function(n) {
                  return '<p><i>'+n[1]+' is editing '+n[2]+' - '+n[3]+'.</i></p>';
	      },

	      'save2': function(n) {
                  return '<p><b>'+n[1]+' has saved '+n[2]+' - '+n[3]+'.</b></p>';
	      }


	  }

	  // default options

	  $.fn.transmission.defaults = {
	      'auth': 'default',
	      'skin': 'small',
	      'delay': 5000,
	      'urlBase': 'http://en.flossmanuals.net/transmission/novi/go.php/transmission/api/',
	      'urlTWiki': 'http://en.flossmanuals.net/bin/transmission'
	  }

      })(jQuery);

