var tssm_enable                       =       1;  //1.5 enable: 1, disable:0
var tssm_version                      =       "1,3,7,5";
var tssm_TimeCountMax                 =       65; // in second(s)
var tssm_test_TimeCountMax            =       5;  // in second(s)
var tssm_ip1                          =       "";
var tssm_ip2                          =       "";
var tssm_ipR                          =       "";
var tssm_did                          =       "";
var tssm_bid                          =       "";
var tssm_type                         =       null;                
var tssm_port                         =       "";
var tssm_time_start;
var tssm_isComplete;
var tssm_isTimeout;
var tssm_installed;
var tssm_id                           = (function(){var date = new Date(); return date.getTime();})();
var tssm_test_RetryCount              =       0;
var tssm_test_RetryCountMax           =       10;
var tssm_test_RetryInterval           =       5;  // in second(s)
var tssmSilent                        =       0;
var tssm_relayCountdown_TimeCount     =       0; // in second
var tssm_relayCountdown_TimeCountMax  =       60; // in second
var tssm_isRelayTimeout               =       0;
var tssm_gotKey                       =       0;

function tssmRest()
{
  tssm_ip1                =       "";
  tssm_ip2                =       "";
  tssm_ipR                =       "";
  tssm_did                =       "";
  tssm_bid                =       "";
  tssm_type               =       null;
  tssm_port               =       "";
  tssm_time_start         =       0;
  tssm_isComplete         =       0;
  tssm_isTimeout          =       0;
  tssm_test_RetryCount    =       0;
}

function tssmClean()
{
  if(tssm_gotKey)
  {
    tssm_gotKey = 0; // means the key is cleaned
    $.ajax(
      {
        type:       "GET",
        url:        tssm_tssmc_url,
        timeout:    1000,
        cache:      false,
        dataType:   "html",
        data:       {
                      "bid":  tssm_bid,
                      "did":  tssm_did
                    },
        success: function(data){},
        error: function(){}
      }
    );
    sleep(1); // sleep 1 sec
  }
}

// Sleep by an ajax with sync mode a cgi programe
function sleep(sec)
{
  $.ajax(
    {
      async:      false,
      type:       "GET",
      url:        tssm_sleep_url,
      timeout:    1000,
      cache:      false,
      dataType:   "html",
      data:       {
                    "src":  sec
                  },
      success: function(data){},
      error: function(){}
    }
  );
}

function tssmLog(mydlink_no, type, state, status, ctype, message)
{
  var type2NO = {
    "8D":               0,
    "LV":               1
  };

  var state2NO = {
    "StartPage":        0,
    "DCPinstalled":     1,
    "ConnectionBegin":  2,
    "ConnectionEnd":    3,
    "TSAinstalled":     4,
    "LeavePage":        5,
    "tssmW":            6,
    "tssmInput":        7,
    "tssmG":            8,
    "tssmConnect1":     9,
    "tssmConnect2":     10
  };

  var status2NO = {
    "Failed":           0,
    "Success":          1
  };

  var ctype2NO = {
    "Local":            1,
    "UPnP":             2,
    "Stunut":           3,
    "Relay":            4
  };

  var post_param = {
    "id":tssm_id,
    "no":mydlink_no,
    "type":(type!="")?type2NO[type]:"",
    "state":(state!="")?state2NO[state]:"",
    "status":(status!="")?status2NO[status]:"",
    "ctype":(ctype!="")?ctype2NO[ctype]:"",
    "browser":encodeURI(navigator.userAgent),
    "message":message
  };

  //alert(array_dump(post_param));


  $.ajax(
    {
      type:       "GET",
      url:        tssm_tssml_url,
      timeout:    1000,
      cache:      false,
      dataType:   "html",
      data:       post_param,
      success: function(data)
      {
        //alert(data);
      },
      error: function(){}
    }
  );
}

function tssmCheckTimeout()
{
  if(tssm_isComplete || tssm_isTimeout) return;
  
  // timeout ?
  var date = new Date();
  if((date.getTime() - tssm_time_start)/1000 >= tssm_TimeCountMax)
  {
    setError("TSSM Timeouted");
    connError();
    tssm_isTimeout = 1;
  }
  setTimeout(arguments.callee, 1000);
}

function tssmKeepAlive()
{
  if(tssm_isTimeout || tssm_isRelayTimeout) return;
  
  try
  {
    $.ajax(
      {
        type:       "GET",
        url:        tssm_tssmg_url+"?key="+tssm_did,
        timeout:    1000,
        cache:      false,
        dataType:   "html",
        data:       "",
        success: function(data){},
        error: function(){}
      }
    );
    setTimeout(arguments.callee, 30*1000);
  }catch(e)
  {
    setTimeout(arguments.callee, 3*1000);
  }
}
function tssmSetup1()
{
  setError("tssmSetup1 ...");
  tssmRest();

  tssmLog(
    mydlink_no,
    tssm_page, // type
    "ConnectionBegin", // state
    "", // status
    "", // ctype
    ""  // message
  );
  
  if(tssm_isTimeout) return;

  CC_Progress_Msg(progressMsg_tssm1);
  // timeout handling !
  var date = new Date();
  tssm_time_start = date.getTime();
  tssmCheckTimeout();

  $.ajax(
    {
      type:       "GET",
      url:        tssm_tssmw_url+"?no="+mydlink_no,
      timeout:    10*1000,
      cache:      false,
      dataType:   "html",
      data:       "",
      success: function(data)
      {
        var temp;
        try
        {
          eval("temp = " + data);
          if(temp.length != 5)
          {
            setError("tssmw error("+data+")");
            tssmError();
          }else
          {
            tssm_gotKey = 1; // got a key ...

            tssm_document.getElementById("input_ip1").value = tssm_ip1 = temp[0];
            tssm_document.getElementById("input_ip2").value = tssm_ip2 = temp[1];
            tssm_document.getElementById("input_ipR").value = tssm_ipR = temp[2];
            tssm_document.getElementById("input_did").value = tssm_did = temp[3];
            tssm_document.getElementById("input_bid").value = tssm_bid = temp[4];
            
            if(
              !verifyIP(tssm_ip1) ||
              !verifyIP(tssm_ip2) ||
              !verifyIP(tssm_ipR) 
            )
            {
              // error ...
              var errorMsg = "IP error("+tssm_ip1+","+tssm_ip2+","+tssm_ipR+")"; 
              setError();
              tssmError();

              tssmLog(
                mydlink_no,
                tssm_page, // type
                "tssmW", // state
                "0", // status
                "", // ctype
                errorMsg  // message
              );

            }else
            {
              tssmLog(
                mydlink_no,
                tssm_page, // type
                "tssmW", // state
                "1", // status
                "", // ctype
                ""  // message
              );

              tssmSetup1_Input1();
            }
          }
        }catch(e)
        {
          // error ...
          setError(data);
          if(data.match(/Exceed Maximum/))
          {
            tssmFull();
          }else if(data.match(/Relay Server full loading/))
          {
            tssmBusy();
          }else
          {
            tssmError();
          }


          tssmLog(
            mydlink_no,
            tssm_page, // type
            "tssmW", // state
            "0", // status
            "", // ctype
            data  // message
          );

        }
      },
      error: function(XMLHttpRequest, textStatus, errorThrown)
      {
        setError("tssmSetup1:connection error");
        tssmError();
      }
    }
  );

}

var inputCount = 0;
function tssmSetup1_Input1()
{
  if(tssm_isTimeout) return;

  /*-- waiting for input --*/
  try
  {
    var delay;
    if(inputCount <= 2)
    {
      // 0 ~ 2
      delay = 1000;
    }else if(inputCount >= 3 && inputCount <= 4)
    {
      // 3 ~ 4
      delay = 5000;
    }else if(inputCount >= 5)
    {
      // 5 ~ N
      delay = 10000;
    }
    TunnelX1.Input(tssm_ip1, tssm_ip2, tssm_ipR);
    setTimeout(tssmSetup1_Input2, delay);
  }catch(e)
  {
    setError(e.message);
    tssmError();

    tssmLog(
      mydlink_no,
      tssm_page, // type
      "tssmInput", // state
      "0", // status
      "", // ctype
      e.message  // message
    );

  }
}

function tssmSetup1_Input2()
{
  switch(parseInt(TunnelX1.OutputResult, 10))
  {
    case 0:
      //alert("input ok");
      tssmSetup2();

      tssmLog(
        mydlink_no,
        tssm_page, // type
        "tssmInput", // state
        "1", // status
        "", // ctype
        ""  // message
      );

      break;

    case -1:
      // error ...
      var errorMsg = "input error("+TunnelX1.OutputResult+")("+tssm_ip1+","+tssm_ip2+","+tssm_ipR+")"; 
      setError(errorMsg);
      tssmError();

      tssmLog(
        mydlink_no,
        tssm_page, // type
        "tssmInput", // state
        "0", // status
        "", // ctype
        errorMsg  // message
      );

      break;
      
    default:
      inputCount++;
      // error ...
      var errorMsg = "input error("+parseInt(TunnelX1.OutputResult, 10)+"!=0)"; 
      setError(errorMsg);
      tssmSetup1_Input1();
      //tssmError();

      tssmLog(
        mydlink_no,
        tssm_page, // type
        "tssmInput", // state
        "0", // status
        "", // ctype
        errorMsg  // message
      );

      break;
  }
}
function tssmSetup2()
{
  if(tssm_isTimeout) return;

  CC_Progress_Msg(progressMsg_tssm2);
  tssm_document.getElementById("input_tssmg").value = "";
  $.ajax(
    {
      type:       "GET",
      url:        tssm_tssmg_url+"?key="+tssm_did,
      timeout:    10*1000,
      cache:      false,
      dataType:   "html",
      data:       "",
      success: function(data)
      {
        tssm_document.getElementById("input_tssmg").value = data;
        switch(parseInt(data, 10))
        {
          case 0:

            //alert("Setup OK");
            tssmConnect1();
  
            tssmKeepAlive();
  
            tssmLog(
              mydlink_no,
              tssm_page, // type
              "tssmG", // state
              "1", // status
              "", // ctype
              ""  // message
            );
            break;
          
          case -2:

            // error ...
            var errorMsg = "tssmg error:device not ready("+data+")"; 
            setError(errorMsg);
            tssmError();
  
            tssmLog(
              mydlink_no,
              tssm_page, // type
              "tssmG", // state
              "0", // status
              "", // ctype
              errorMsg  // message
            );
            break;
          default:
  
            tssmLog(
              mydlink_no,
              tssm_page, // type
              "tssmG", // state
              "0", // status
              "", // ctype
              data  // message
            );

            var errorMsg = "tssmg error:("+data+")"; 
            setError(errorMsg);
  
            setTimeout(tssmSetup2, 1000);
            break;
        }
      },
      error: function(XMLHttpRequest, textStatus, errorThrown)
      {
        setError("tssmSetup2:connection error");
        tssmError();
      }
    }
  );
}
function tssmConnect1()
{
  if(tssm_isTimeout) return;

  /*-- waiting for client connect --*/
  //TunnelX1.Stop(tssm_bid);
  TunnelX1.ClientConnect(tssm_did, tssm_bid);
  if(parseInt(TunnelX1.OutputResult, 10) == 0)
  {
    tssmLog(
      mydlink_no,
      tssm_page, // type
      "tssmConnect1", // state
      "1", // status
      "", // ctype
      ""  // message
    );

    setTimeout(tssmConnect2,1000);
  }else
  {
    // error ...
    var errorMsg = "tssmConnect1 error("+TunnelX1.OutputResult+")"; 
    setError(errorMsg);
    setTimeout(arguments.callee, 1000);
    //tssmError();

    tssmLog(
      mydlink_no,
      tssm_page, // type
      "tssmConnect1", // state
      "0", // status
      "", // ctype
      errorMsg  // message
    );
  }
}

function tssmConnect2()
{
  if(tssm_isTimeout) return;
  setError("");
  
  TunnelX1.GetResult(tssm_bid);
  var patConnect = new RegExp("0,1,([0-9]+),([0-9]+)");
  var resultStr = TunnelX1.OutputResult;
  var m;
  if(m = String(resultStr).match(patConnect))
  {
    tssm_isComplete = 1;
    tssm_type = m[1];
    tssm_port = m[2];
    setError("http://127.0.0.1:"+tssm_port);
    //alert(array_dump(m));
    connTestTSSM();

    tssmLog(
      mydlink_no,
      tssm_page, // type
      "tssmConnect2", // state
      "1", // status
      tssm_type, // ctype
      errorMsg  // message
    );
  }else
  {
    var errorMsg = "tssmConnect2("+TunnelX1.OutputResult+")"; 
    setError(errorMsg);
    setTimeout(arguments.callee, 1000);

    tssmLog(
      mydlink_no,
      tssm_page, // type
      "tssmConnect2", // state
      "0", // status
      "", // ctype
      errorMsg  // message
    );
  }
}

function array_dump(arr)
{
  var str = "";
  for(a in arr) str+="["+a+"]"+String(arr[a])+"\n";
  return str;
}

function verifyIP (IPvalue)
{
  var ipPattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
  var ipArray = IPvalue.match(ipPattern);
  var i, thisSegment;
  
  if (IPvalue == "0.0.0.0" || IPvalue == "255.255.255.255" || ipArray == null)
  {
    return false;
  }
  else 
  {
    for (i = 0; i < 4; i++) 
    {
      thisSegment = ipArray[i];
      if (thisSegment > 255 || ((i == 0) && (thisSegment > 255)))
      {
        return false;
      }
    }
  }
  
  return true;
}