
(function() {

  // 2008-09-23
  function MSocket(data) {

    this.listener = {};

    for (i in data) {
      this[i] = data[i];
    }

    this.mgr = document.msock;
    this.mgr.register(this);
  }

  // o: listening object.
  // e: event name, defaults to Connect, Close, DataReceived.
  MSocket.prototype.addListener = function msocket_addListener(o, e) {

    if (e == null)
        e = [ 'Connect', 'Close', 'DataReceived' ];

    if (!xb.isArray(e))
        e = [ e ];

    // Only one listener per event?  Seems reasonable.
    for (var i = 0 ; i < e.length ; i++) {
        this.listener[e[i]] = {
            object: o,
            callback: ('on' + e[i])
        };
    }
  }

  // 2008-10-07
  MSocket.prototype.handleOperation = function msocket_handleOperation(o) {
      if (this.TRACE)
          dd("Socket notified of operation: " + xb.dumpObject(o));

      if (o.event == 'connect') {
          var l = this.listener['Connect'];
          if (l)
              l.object[l.callback].apply(l.object, [o]);

          return;
      }

      if (o.event == 'read') {
          var l = this.listener['DataReceived'];
          if (l)
              l.object[l.callback].apply(l.object, [o]);

          return;
      }

      if (o.event == 'close') {
          var l = this.listener['Close'];
          if (l)
              l.object[l.callback].apply(l.object, [o]);

          return;
      }

  }

  // 2008-09-23
  // Default host should be the host of the page.
  MSocket.prototype.requestConnect = function msocket_requestConnect() {

    if (!this.host) {
      var x = window.location.host;
      var y = x.indexOf(":");

      if (y >= 0) {
        x = x.substr(0, y);
      }

      this.host = x;
    }

    if (!this.port)
      this.port = 8081;

    dd("Connecting to: " + this.host + ":" + this.port);

    //dd("this.mgr: " + this.mgr);
    //dd("this.mgr.giatube: " + this.mgr.giatube);
    this.mgr.giatube.requestConnect(this.id, this.host, this.port);
  };

  // 2008-09-23
  MSocket.prototype.requestSend = function msocket_requestSend(data) {
    this.mgr.giatube.requestSend(this.id, data);
  };

  // 2008-09-23
  MSocket.prototype.requestClose = function msocket_requestClose() {
    alert("Msocket requesting close");
  };

  document.MSocket = MSocket;

  var msock = document.msock = {};

  // 2008-09-22
  msock.init = function msock_init () {

    $('#socket_console').Resizable
    (
     {
         minWidth: 200,
         minHeight: 60,
         maxWidth: 1000,
         maxHeight: 500,
         dragHandle: '#socket_console_handle',
         handlers: {
           se: '#socket_console_resize'
         },
         onResize : function(size, position) {
         //$('#windowBottom, #windowBottomContent').css('height', size.height-33 + 'px');
         var consoleContent = $('#socket_console_content').css('width', size.width - 25 + 'px');
         consoleContent.css('height', size.height - 55 + 'px');
       }
       }
       );

    this.socketCount = 0;
    this.cycleCount = 0;
    this.socket = [];

    this.giatube = $('#GiaTube').get(0);

    document.mevent.preCycle.push(function() { document.msock.cycle(); });

    dd("MSock initialized");
  };

  msock.register =
  function msock_register(s) {

    s.id = ++this.socketCount;
    this.socket[s.id] = s;
  }
  // 2008-09-22
  msock.cycle = function msock_cycle() {

    if (!("cycle" in this.giatube)) {
      dd("giatube cycle not yet available");
      return;
    }

    this.cycleCount++;

    if (this.TRACE)
        dd("MSock cycle: " + this.cycleCount);

    var response = this.giatube.cycle();

    if (this.TRACE)
        dd("msock.cycle giatube response: " + response);

    //response = response.replace(/\r/g, "\\r");
    //response = response.replace(/\n/g, "\\n");
    var operations;

    try {
      operations = eval(response);
    } catch (e) {
      alert(e);
      alert("RESPONSE: " + response);
    }

    if (xb.isArray(operations)) {
      for (var i = 0 ; i < operations.length ; i++) {
        var o = operations[i];

        if (o.id && o.id in this.socket) {
            this.socket[o.id].handleOperation(o);
        }
      }
    }

  };


  msock.default_onDataRecieved =
  function mchat_onDataReceived(e) {

      if (!("incoming" in this))
          this.incoming = "";

      this.incoming += e.data;

      if (this.incoming.length == 0)
          return;

      var incomplete = this.incoming.charAt(this.incoming.length-1) != '\n';

      var cmds = this.incoming.split("\n");

      if (incomplete) {
          this.incoming = cmd[cmd.length-1];
          delete cmd[cmd.length-1];
      } else {
          this.incoming = "";
      }

      var cmdMatcher = /(\w+)(?:\s+(.*))?/;
      for (var i = 0 ; i < cmds.length ; i++) {

          var l = cmds[i];

          if (!cmds[i].length)
              continue;

          dd('Line received: ' + l);

          var c = cmdMatcher.exec(l);
          var cmd;
          var args = null;
          if (c) {
              cmd = c[1];
              if (c.length > 1) {
                  try {
                      args = eval("(function() { return " + c[2] + "; })()");
                  } catch (ex) {
                      alert("Exception: " + ex + " while evaling " + c[1] + " ... " + c[2]);
                  }
              }
          }

          if (cmd) {
              if (!args)
                  args = {};
              args.name = cmd;
              document.mevent.append(args);
          }
      }
  };

})();

document.mready.push({
    callback: function() { document.msock.init(); },
    runlevel: 10,
    description: 'msock init'});

