/**************************************************************
 DLDPShell.js
 Date: 2009.2
**************************************************************/


function DLDPShell()
{
  this._class;
  this._classType;
  this._TimeCount;
  this._TimeCountMax;
  this._isTimeouted;
  this._TriggerRestartTimeCount;
  this._TriggerRestartTimeCountMax;
  this._RestartTimeCount;
  this._RestartTimeCountMax;
  this._HTTPGetTimeCount;
  this._HTTPGetTimeCountMax;
  this._RetryCount;
  this._RetryCountMax;
  this._SleepBeforeWaitingLoop;
  this._str1;
  this._str2;
  this._paramT;
  this._paramR;
  this._itemR;
  this._parent;
  
  this.ResetDefault();
}

DLDPShell.prototype = {
  ResetDefault:function()
  {
    this._class;
    this._classType = 2;
    this._TimeCount = 0;
    this._TimeCountMax = 90;
    this._isTimeouted = 0;
    this._TriggerRestartTimeCount = 0;
    this._TriggerRestartTimeCountMax = 60;
    this._RestartTimeCount = 0;
    this._RestartTimeCountMax = 60;
	  this._HTTPGetTimeCount = 0;
	  this._HTTPGetTimeCountMax = 5;
    this._RetryCount = 0;
    this._RetryCountMax = 1;
    this._SleepBeforeWaitingLoop = 0;
    this._str1 = "";
    this._str2 = "";
    this._paramT = [];
    this._paramR = [];
    this._itemR = [];
    this._parent;
  },
  ResetCount:function()
  {
    this._TimeCount = 0;
    this._RestartTimeCount = 0;
    this._RetryCount = 0;
  },
  Query:function(cls, param)
  {
    this._isTimeouted = 0;
    this.ResetCount();
    this.DoQuery(cls, param);
  },

  // send a request to DLDP server ...
  DoQuery:function(cls, param)
  {
    this.BeforeQuery();
    
    // reset all of the data ...
    this._paramT = [];
    this._paramR = [];
    this._itemR = [];

    // class type
    // 1: stream mode
    // 2: param mode
    this._class = cls;
    switch(this._class)
    {
      case 1:
          this._classType = 1;
          break;
          
      case 4:
          this._classType = 1;
          break;
          
      default:
          this._classType = 2;
          break;
    }

    this._paramT  = param;
    var cmd = [
        this._class
      , "M=" + this._paramT['M']
      , "D=" + this._paramT['D']
    ];
    for (var p in this._paramT) {
      'M' !== String(p).toUpperCase() && 'D' !== String(p).toUpperCase() && cmd.push(p + "=" + this._paramT[p]);
    }
    cmd = cmd.join(';');
    //alert(cmd);
    this.DLDPExec("CLS");
    this.DLDPExec(cmd);

    
    this.AfterQuery();

    var thisObj = this;
    setTimeout(function(){thisObj.waiting_loop();}, this._SleepBeforeWaitingLoop*1000);
  },
  
  
  
  // waiting for response ...
  waiting_loop:function()
  {

    if(this._TimeCount > this._TimeCountMax)
    {
      if(this._RetryCount < this._RetryCountMax)
      {
        this._TimeCount = 0;
        this._RetryCount++;
        this.DoQuery(this._class, this._paramT);
      }else
      {
        this.Timeout();
        this._isTimeouted = 1;
      }
      return;
    }

    //top.document.title = DLDP.str2+"("+this._TimeCount+")("+this._RetryCount+")";


    // data received and without error...
    this._str2 = DLDP.str2;
    switch(this._classType)
    {
      case 1:
          re = new RegExp("^"+this._class+".*");
         	if(this._str2.match(re))
         	{
            temp = this._str2.split(',');
            for(t in temp) this._itemR.push(temp[t]);

            this.Complete();
            return;

         	}
          break;
      case 2:
          if(this._paramT["M"] != undefined && this._paramT["M"] != undefined)
          {
           	re = new RegExp("^"+this._class+";M="+this._paramT["M"]+";D="+this._paramT["D"]+".*");
           	if(this._str2.match(re))
           	{
              temp = this._str2.split(';');
              for(t in temp)
              {
                if(m = temp[t].match(/(^[^=]+)=(.*)/)) this._paramR[m[1]] = m[2];
              }
              this.Complete();
              return;
           	}
          }
          break;
    }


    this._TimeCount++;
    var thisObj = this;
    setTimeout(function(){thisObj.waiting_loop();}, 1000);
  },
  
  
  // waiting for trigger restart network ...
  waiting_trigger_restart_loop:function()
  {
    if(this._TriggerRestartTimeCount > this._TriggerRestartTimeCountMax)
    {
      this.TriggerNetworkRestartTimeout();
      this._isTimeouted = 1;
      return;
    }

    // data received and without error...
    this._str2 = DLDP.str2;
    //re = new RegExp("^9;.+");
    re = new RegExp("^9;M="+this._paramT["M"]+";D="+this._paramT["D"]+".+");
   	if(this._str2.match(re))
   	{
   	  this.TriggerNetworkRestartComplete();
      this.waiting_restart_loop();
      return;
   	}
    this.WhileTriggerNetworkRestarting();

    this._TriggerRestartTimeCount++;
    var thisObj = this;
    setTimeout(function(){thisObj.waiting_trigger_restart_loop();}, 1000);
  },
  TriggerNetworkRestart:function()
  {
    var cmd = "9;M="+this._paramT["M"]+";D="+this._paramT["D"]+";N=1";
    this.DLDPExec(cmd);
    this.waiting_trigger_restart_loop();
  },
  TriggerNetworkRestartTimeout:function(){
    //alert("restart trigger timeout");
    this.Timeout();
  },
  TriggerNetworkRestartComplete:function()
  {
  },
  WhileTriggerNetworkRestarting:function(){},


  // waiting for restart network ...
  waiting_restart_loop:function()
  {
    if(this._RestartTimeCount > this._RestartTimeCountMax)
    {
      this.NetworkRestartTimeout();
      this._isTimeouted = 1;
      return;
    }

    //top.document.title = DLDP.str2+"("+this._RestartTimeCount+")(0)";


    // data received and without error...
    this._str2 = DLDP.str2;
    re = new RegExp("^5;M="+this._paramT["M"]+";D="+this._paramT["D"]+".+");
   	if(this._str2.match(re))
   	{
      this.RestartComplete();
      return;
   	}
    this.WhileNetworkRestarting();



    // actively query for class5 while waiting for network restart!!
    if(this._RestartTimeCount > 5) // sleep 5 sec
    {
      var cmd = "5;M="+this._paramT["M"]+";D="+this._paramT["D"];
      this.DLDPExec(cmd);
    }



    this._RestartTimeCount++;
    var thisObj = this;
    setTimeout(function(){thisObj.waiting_restart_loop();}, 1000);
  },


  // do something when timeout ...
  Timeout:function(){},
  NetworkRestartTimeout:function(){
    //alert("restart timeout");
    this.Timeout();
  },
  WhileNetworkRestarting:function(){},

  TriggerHTTPRestart:function()
  {
    var cmd = "9;M="+this._paramT["M"]+";D="+this._paramT["D"]+";L=1";
    this.DLDPExec(cmd);
  },


  Error:function(){},
  Complete:function(){},
  BeforeQuery:function(){},
  AfterQuery:function(){},
  RestartComplete:function(){},  
  
  DLDPExec:function(cmd)
  {
    this._str1 = this.cmd_add_length(cmd);
    DLDP.str1 = this.cmd_add_length(cmd);
  },
  DLDPStart:function()
  {
    var cmd = "START DLDP";
    this.DLDPExec(cmd);
  },
  DLDPStop:function()
  {
    var cmd = "STOP DLDP";
    this.DLDPExec(cmd);
  },
  DLDPDebug:function()
  {
    var cmd = "START DEBUG";
    this.DLDPExec(cmd);
  },
  DLDPRestart:function()
  {
    var cmd = "STOP DLDP";
    this.DLDPExec(cmd);
    var cmd = "START DLDP";
    this.DLDPExec(cmd);
  },
	HTTPGet:function(url)
	{
    this.DLDPExec("CLS");
		this.DLDPExec("START HTTP,"+url);
		this.HTTPGET_waiting_loop();
	},
	HTTPGetAuth:function(url, auth_string)
	{
	  // auth_string is a base64-encoded string contains "username:password"
    this.DLDPExec("CLS");
		this.DLDPExec("START HTTP,"+url+","+auth_string);
		this.HTTPGET_waiting_loop();
	},
	HTTPGET_waiting_loop:function()
	{
    if(this._HTTPGetTimeCount > this._HTTPGetTimeCountMax)
    {
      this.HTTPGetTimeout();
      this._isTimeouted = 1;
      return;
    }

    // data received and without error...
    this.DLDPExec("GET HTTP");
    this._str2 = DLDP.str2;
    if(this._str2!="")
   	{
      this.HTTPGetComplete();
      return;
   	}
    this._HTTPGetTimeCount++;
    var thisObj = this;
    setTimeout(function(){thisObj.HTTPGET_waiting_loop();}, 1000);	
	}, 
	HTTPGetTimeout:function()
	{
	},
	HTTPGetComplete:function()
	{
	},
  
  // added the length of a command in front of the command ...
  cmd_add_length:function(cmd)
  {
    return cmd = this.getBytes(cmd)+","+cmd;
  },
  array_dump:function(arr)
  {
    var str = "";
    for(a in arr)
    {
      str+="["+a+"]"+String(arr[a])+"\n";
    }
    return str;
  },
  getBytes:function(str)
  {
    var cArr = str.match(/[^\x00-\xff]/ig);    
    return str.length + (cArr == null ? 0 : cArr.length);    
  }  


};

