﻿// lingrcom.js
//
// Lingr Communication Javascript Class
// ver 0.01  2007/05/05 
// ver 0.02  2007/05/06 Bug fix on IE
// Copyright 2007 Inutsuka Yusuke (inutch)   http://d.hatena.ne.jp/inutch/


//set cgi path
var lingrcom_cgipath = "./scripts/cgi/";

// implementation of bind //
if( typeof( window.Function.prototype.bind ) == "undefined" ){
  Function.prototype.bind = function(object) {
    var __method = this;
    return function() {
      return __method.apply(object, arguments);
    };
  };
}


// Common Function //

if( typeof( window.txt2json ) == "undefined" ){
  function txt2json(str)
  {
    return eval( "(" + str + ")" );
  }
}

if( typeof( window.displog ) == "undefined" ){
  function displog(str)
  {
    try{
      console.debug(str);
    }
    catch(e){
    }
  }
}


/////// Lingr Communicasion Class //////////////////////////////////////////////


function LingrCom(myname)
{
  //g_lingrcom_prefix_cnt is global variable common between multiple LingrCom object
  if( typeof(g_lingrcom_prefix_cnt) == "undefined" ){
    g_lingrcom_prefix_cnt = 0;
  }

  this.objname = myname;

  this.session_id = null;
  this.my_id = null;
  this.room_ticket = null;
  this.nickname = null;

  this.room_counter = null;
  this.room_max_obs_time = null;
  this.obs_timer = null;

  this.say_obj = null;
  this.say_cb_func = null;

  this.observe_obj = null;
  this.observe_cb_func = null;

  this.getmsgs_obj = null;
  this.getmsgs_cb_func = null;

  this.ocpchange_cb_func = null;

}


//start prototype
LingrCom.prototype = {


  createJSONRequest:function(url)
  {
    var uniqid = g_lingrcom_prefix_cnt;
    var obj = document.createElement("script");
    obj.setAttribute("type", "text/javascript");
    obj.setAttribute("charset", "utf-8");
    obj.setAttribute("src", url + "&noCacheIE=" + uniqid );
    obj.setAttribute("id", "jsonreq" + uniqid);
    document.getElementsByTagName("head").item(0).appendChild(obj);
    return obj;
  },


  deleteJSONRequest:function(obj)
  {
    document.getElementsByTagName("head").item(0).removeChild(obj);
  },


  createXMLHttpRequest:function(cb)
  {
    var httpobj = null;
    try{
      httpobj = new XMLHttpRequest();
    }catch(e){
      try{
        httpobj = new ActiveXObject("Msxml2.XMLHTTP");
      }catch(e){
        try{
          httpobj = new ActiveXObject("Microsoft.XMLHTTP");
        }catch(e){
          return null;
        }
      }
    }
    if (httpobj && cb) {
      httpobj.onreadystatechange = cb;
    }
    return httpobj;
  },


  httpStateCheck:function(http)
  {
    if ((http.readyState == 4) && (http.status == 200)){
      return true;
    }
    else{
      return false;
    }
  },


  createSession:function()
  {
    var ret = false;
    var httpobj = this.createXMLHttpRequest(null);
    if(httpobj){
      httpobj.open("POST", lingrcom_cgipath+"ses.cgi", false);
      httpobj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      httpobj.send('');
      if( this.httpStateCheck(httpobj) ){
        var data = txt2json(httpobj.responseText);
        this.session_id = data.session;
        ret = true;
        displog(this.objname + ".createSession: OK, session_id=" + this.session_id);
      } else {
        displog(this.objname + ".createSession: NG (http stete check)");
      }
    } else {
      displog(this.objname + ".createSession: NG (createXMLHttpRequest)");
    }
    return ret;
  },


  enterRoom:function(roomid, nickname)
  {
    var ret = false;
    var httpobj = this.createXMLHttpRequest(null);
    if(httpobj){
      httpobj.open("POST", lingrcom_cgipath+"room.cgi", false);
      httpobj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      var sendstr = 'format=json'
         + '&session=' + this.session_id
         + '&id=' + roomid;
      if(nickname){
         sendstr += '&nickname=' + nickname;
      }
      httpobj.send( sendstr );
      if( this.httpStateCheck(httpobj) ){
        var data = txt2json(httpobj.responseText);
        this.room_counter = data.room.counter;
        this.room_ticket = data.ticket;
        this.my_id = data.occupant_id;
        this.room_max_obs_time = data.max_observe_time;
        ret = true;
        displog(this.objname + ".enterRoom: OK"
                  + ", counter=" + this.room_counter
                  + ", ticket=" + this.room_ticket
                  + ", maxtime=" + this.room_max_obs_time);
        if(data.occupants != undefined && this.ocpchange_cb_func){
          this.ocpchange_cb_func(data.occupants);
        }

      } else {
        displog(this.objname + ".enterRoom: NG (http stete check)");
      }
    } else {
      displog(this.objname + ".enterRoom: NG (createXMLHttpRequest)");
    }
    return ret;
  },


  setNickname:function(nickname)
  {
    var ret = false;
    var httpobj = this.createXMLHttpRequest(null);
    if(httpobj){
      httpobj.open("POST", lingrcom_cgipath+"nick.cgi", false);
      httpobj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      httpobj.send(
           'format=json'
           + '&session=' + this.session_id
           + '&ticket=' + this.room_ticket
           + '&nickname=' + nickname
           );
      if( this.httpStateCheck(httpobj) ){
        var data = txt2json(httpobj.responseText);
        if(data.status == 'ok') {
          this.nickname = nickname;
          ret = true;
          displog(this.objname + ".setNickname: OK");
        } else {
          displog(this.objname + ".setNickname: NG (return status)");
        }
      } else {
        displog(this.objname + ".setNickname: NG (http stete check)");
      }
    } else {
      displog(this.objname + ".setNickname: NG (createXMLHttpRequest)");
    }
    return ret;
  },


  say:function(str, cb)
  {
    if(cb){
      this.say_cb_func = cb;
    }
    this.say_obj = this.createXMLHttpRequest(this.cb_say.bind(this));
    if(this.say_obj){
      this.say_obj.open("POST", lingrcom_cgipath+"say.cgi", true);
      this.say_obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      this.say_obj.send(
           'format=json'
           + '&session=' + this.session_id
           + '&ticket=' + this.room_ticket
           + '&message=' + str
           );
      displog(this.objname + ".say: msg=" + str);
    }
    else{
      displog(this.objname + ".say: NG (createXMLHttpRequest)");
    }
  },


  cb_say:function()
  {
    if( this.httpStateCheck(this.say_obj) ){
      var data = txt2json(this.say_obj.responseText);
      displog(this.objname + ".cb_say: text=" + data.message.text);
      if( this.say_cb_func ){
        this.say_cb_func(data.message);
      }
    }
  },


  observe:function(cb)
  {
    if(cb){
      this.observe_cb_func = cb;
    }
    var str = 'http://' + ( g_lingrcom_prefix_cnt++ ) + '.www.lingr.com/api/room/observe?'
             + 'format=json'
             + '&session=' + this.session_id
             + '&ticket=' + this.room_ticket
             + '&counter=' + this.room_counter
             + '&callback=' + this.objname + '.cb_observe'
             ;
    //displog(this.objname + ".observe :" + str);
    this.observe_obj = this.createJSONRequest(str);
    this.obs_timer = setTimeout(this.cb_obs_timeout.bind(this), 115*1000);
  },


  cb_observe:function(data)
  {
    //clear timer
    if(this.obs_timer){
      clearTimeout(this.obs_timer);
    }
    //http status check
    if( data.status != 'ok') { 
      displog(this.objname + ".cb_observe: NG (status)");
      return false;
    }
    //update counter
    if( data.counter == undefined ){
      displog(this.objname + ".cb_observe: Nothing happened");
    } else {
      this.room_counter = data.counter;
      if( data.messages == undefined ){
        displog(this.objname + ".cb_observe: No Messages");
      } else {
        displog(this.objname + ".cb_observe: OK, text=" + data.messages[0].text);
        if( this.observe_cb_func ){
          this.observe_cb_func(data.messages);
        }
      }
      if( data.occupants != undefined && this.ocpchange_cb_func ){
        this.ocpchange_cb_func(data.occupants);
      }
    }
    //remove dynamic script
    this.deleteJSONRequest(this.observe_obj);
    //restart observe
    this.observe();
  },


  cb_obs_timeout:function()
  {
    displog(this.objname + ".cb_obs_timeout");
    //remove dynamic script
    this.deleteJSONRequest(this.observe_obj);
    //restart observe
    this.observe();
  },


  getMessages:function(num, cb)
  {
    if(cb){
      this.getmsgs_cb_func = cb;
    }
    this.getmsgs_obj = this.createXMLHttpRequest(this.cb_getmessages.bind(this));
    if(this.getmsgs_obj){
      this.getmsgs_obj.open("POST", lingrcom_cgipath+"msgs.cgi", true);
      this.getmsgs_obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      this.getmsgs_obj.send('format=json'
          + '&session=' + this.session_id
          + '&ticket=' + this.room_ticket
          + '&counter=' + num
          );
      displog(this.objname + ".getMessages: " + num);
    }
  },


  cb_getmessages:function()
  {
    if( this.httpStateCheck(this.getmsgs_obj) ){
      var data = txt2json(this.getmsgs_obj.responseText);
      if (data.messages == undefined ){
        displog(this.objname + ".cb_getmessages: No Messages");
        this.getmsgs_cb_func(null);
      } else {
        displog(this.objname + ".cb_getmessages: OK, num=" + data.messages.length);
        this.getmsgs_cb_func(data.messages);
      }
    }
  },


  setOcupantsChangeCallback:function(cb)
  {
    this.ocpchange_cb_func = cb;
  },


  leaveRoom:function()
  {
    var httpobj = this.createXMLHttpRequest(null);
    if(httpobj){
      httpobj.open("POST", lingrcom_cgipath+"exit.cgi", false);
      httpobj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      httpobj.send(
           'format=json'
           + '&session=' + this.session_id
           + '&ticket=' + this.room_ticket
           );
      if( this.httpStateCheck(httpobj) ){
        var data = txt2json(httpobj.responseText);
        if(data.status == 'ok') {
          displog(this.objname + ".leaveRoom: OK");
        }
      }
      else{
        displog(this.objname + ".leaveRoom: NG");
      }
    }
    else{
      displog(this.objname + ".leaveRoom: NG (createXMLHttpRequest)");
    }
  },


  destroySession:function()
  {
    var httpobj = this.createXMLHttpRequest(null);
    if(httpobj){
      httpobj.open("POST", lingrcom_cgipath+"destroy.cgi", true);
      httpobj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      httpobj.send(
           'format=json'
           + '&session=' + this.session_id
           );
      displog(this.objname + ".destroySession");
    }
    else{
      displog(his.objname + ".destroySession: NG (createXMLHttpRequest)");
    }
  }


};
//end prototype


/////// Lingr Communicasion Class //////////////////////////////////////////////

