
function setCharAt(str,index,char) {
  if(index > str.length-1) return str;
  return(str.substr(0,index) + char + str.substr(index+1));
}

var loaded=false;
var sWidth;
var sHeight;



function handleCommand(arg){
  linfo("command: "+arg.type);
  switch (arg.type){
    case "msg":
      userTalk(arg);
     break;
    case "join":
      userJoin(arg);
     break;
    case "login":
      userLogin(arg);
     break;
//    case "output":
//      serverOutput(arg);
//     break;
    case "result":
      serverResult(arg);
     break;
  }
}

function doReceiveData(data){
  if (data.length==0 || loaded==false) return;
  linfo("data: "+data);

  var cmds=JSON.parse(data);
//  var cmds=data.split(";");

  if (typeof cmds.length != 'undefined'){
    for (var i=0; i<cmds.length; ++i)
      handleCommand(cmds[i]);
  }else if (typeof cmds.type != 'undefined'){
    handleCommand(cmds);
  }else{
    lerror("message from server with no commands");
  }
}

var users={};

function userLogin(args){
  if (args.login==0){
    linfo("login failed");
    return;
  }
  $('loginwin').style.visibility='hidden';
  linfo("login successful");
}
function userJoin(args){
  users[args.uid]={user:args.user};
}
function userTalk(args){
  if (!(args.uid in users)) { lerror("user: "+args.user+" not in list!"); return; }
  $('chat').innerHTML+=args.uid+"> "+args.msg+"<br>";
}
function serverOutput(args)
{
  args.output=args.output.replace(/\n/g,"<br/>");
  $('consoleout').innerHTML+=args.output;
}

var serverResults=[];
function serverResult(args){
  serverResults.push(args.result);
  $('consoleout').innerHTML+="<a href=\"#\" onclick=\"doShowResult("+(serverResults.length-1)+");return(false);\">new window</a><br/>"+evarOutput(args.result)+"<br/>";
}

function popupMenuShow(e){
  e=e||window.event;
  $('popupmenu').innerHTML='<a href="#">Option1</a><br/><a href="#">Option2</a><br/><a href="#">Option3</a><br/><a href="#">Option4</a>';
  $('popupmenu').style.left=e.pageX+"px";
  $('popupmenu').style.top=e.pageY+"px";
  $('popupmenu').style.visibility="visible";
}

function etableSort() {
  alert("table sort");
}


function evarOutput(v){
  var str="";
  if (v.t=="i" || v.t=="d" || v.t=="f" || v.t=="u" || v.t=="j" || v.t=="c" || v.t=="4estr"){
    return(v.d);
  } else if (v.t=="9estrarray"){
    str='<table class="etable"><tr><th>key</th><th>value</th></tr>';
    for (var i=0; i<v.d.length; ++i)
      str+="<tr><td>"+v.d.keys[i].d+"</td><td>"+v.d.values[i].d+"</td></tr>";
    str+="</table>";
    return(str);
  } else if (v.t=="6etable"){
    if (v.d.fields.length==0) return("empty table");
    str='<table class="etable">';
    str+='<tr><th></th>';
    for (var i=0; i<v.d.fields.length; ++i)
      str+='<th>'+v.d.fields[i]+"</th>";
    str+="</tr>";
    for (var i=0; i<v.d.cols.length; ++i){
      str+='<tr><td>'+i+"</td>";
      for (var j=0; j<v.d.cols[i].length; ++j){
        str+='<td>'+v.d.cols[i][j].d+"</td>";
      }
      str+="</tr>";
    }
    str+="</table>";
    return(str);
  }
  return(v.t);
}


function doShowResult(i){
  var res=serverResults[i];
  if (res.t=="9estrarray"){
    var str="";
    str='<table class="etable" style="width:50%"><tr><th>key</th><th>value</th></tr>';
    for (var i=0; i<res.d.length; ++i)
      str+="<tr><td>"+res.d.keys[i].d+"</td><td>"+res.d.values[i].d+"</td></tr>";
    str+="</table>";
    $('inspector').innerHTML=str;
    $('inspectorwin').style.visibility="visible";
    windowBringToFront($('inspectorwin'));
  } else if (res.t=="6etable"){
    str='<svg>';
    str+='<polyline points="1,1 1,350 350,350" style="stroke:black;stroke-width:2px;fill:none"/>';
    for (var i=0; i<res.d.cols.length; ++i){
      str+='<circle cx="'+(parseFloat(res.d.cols[i][0].d)+1.0)+'" cy="'+(350.0-parseFloat(res.d.cols[i][1].d))+'" r="5" style="stroke:black;stroke-width:1px;fill:none"/>';
    }
    str+='</svg>'
    alert(str);
    $('inspector').innerHTML=str;
    $('inspectorwin').style.visibility="visible";
    windowBringToFront($('inspectorwin'));
  } else if (res.t=="6etable"){
    var str="";
    if (res.d.fields.length==0) return;

    str='<table class="etable">';
    str+='<tr><th></th>';
    for (var i=0; i<res.d.fields.length; ++i)
      str+='<th><a href="#" onclick="etableSort();return(false);" oncontextmenu="popupMenuShow();return(false);">'+res.d.fields[i]+"</a></th>";
    str+="</tr>";
    for (var i=0; i<res.d.cols.length; ++i){
      str+='<tr><td>'+i+"</td>";
      for (var j=0; j<res.d.cols[i].length; ++j){
        str+='<td>'+res.d.cols[i][j].d+"</td>";
      }
      str+="</tr>";
    }
    str+="</table>";
    $('inspector').innerHTML=str;
    $('inspectorwin').style.visibility="visible";
    windowBringToFront($('inspectorwin'));
  }
}



function doReceiveStatus(text){
  linfo("got status: "+text);
  var args = JSON.parse(text);
  for (var i=0; i<args.users.length; ++i)
    userJoin(args.users[i]);
  for (var i=0; i<args.acdbWords.length; ++i)
    acdbAdd(args.acdbWords[i]);
}

var history=[];
var histpos=-1;
var histedit="";

function initChat(){
//  var tag=document.createElement("div");
//  document.body.appendChild(tag);

//  $('chatline').onkeydown=chatHandleKeyDown;
//  $('chatline').onkeyup=chatHandleKeyUp;

  $('prompt').onkeydown=promptHandleKeyDown;
  $('prompt').onkeyup=promptHandleKeyUp;

  $('consolewin').edit=$('prompt');
  $('chatwin').edit=$('chatline');

  setMovable($('logwin'));
  setMovable($('inspectorwin'));
  setMovable($('chatwin'));
  setMovable($('consolewin'));


  $('statuswin').style.top=(-$('statuswin').offsetHeight)+"px";
  var tmp=$('statuswin').offsetTop;
  $('statuswin').style.visibility='visible';
/*  $('statuswin').className="statusshow"; */
  $('statuswin').style.transition='top 0.5s linear';
  $('statuswin').style.webkitTransition='top 0.5s linear';
  $('statuswin').style.top="0";

  $('prompt').focus();
}

function hideInspector(){
  $('inspectorwin').style.visibility="hidden";
}

var acdbRoot={words:[]};
var acdbWords=[];
function acdbAdd(s){
  var p=acdbRoot;
  acdbRoot.words.push(s);
  for (var i=0; i<s.length; ++i){
    if (typeof p[s.charAt(i)] == 'undefined')
      p[s.charAt(i)]={words:[]};
    p=p[s.charAt(i)];
    p.words.push(s);
  }
}
function acdbList(s){
  var p=acdbRoot;
  for (var i=0; i<s.length; ++i){
    if (typeof p[s.charAt(i)] == 'undefined')
      return([]);
    p=p[s.charAt(i)];
  }
  return(p.words);
}
var acdbTimeout=null;
function acdbUpdate(){
  if ($('autocomplete').style.visibility=="visible"){
    acdbShow();
    return;
  }
  if (acdbTimeout!=null)
    clearTimeout(acdbTimeout);
  acdbTimeout=setTimeout(acdbShow,300);
}
function acdbShow(){
  /* auto-complete (tabkey) */
  if ($('prompt').value.length==0){
    acdbHide();
    return;
  }
  var s=$('prompt').value;
  var wlist=acdbList(s);
  if (wlist.length==0){
    if ($('autocomplete').style.visibility=="visible")
      acdbHide();
    return;
  }
  $('autocomplete').innerHTML="";
  for (var i=0; i<wlist.length; ++i)
    $('autocomplete').innerHTML+='<span style="color:#55f">'+wlist[i].substr(0,s.length)+'</span>'+wlist[i].substr(s.length)+"<br/>";
  var r=$('prompt').getBoundingClientRect();
  $('autocomplete').style.left=r.left+"px";
  $('autocomplete').style.top=r.bottom+"px";
  $('autocomplete').style.visibility="visible";
}
function acdbHide(){
  $('autocomplete').style.visibility="hidden";
}

function promptHandleKeyUp(e){
  var code = (e.keyCode ? e.keyCode : e.which);
  if (code==27 || code>=37 && code <=40) return(false);
  acdbUpdate();
  return(true);
}
function promptHandleKeyDown(e){
  var code = (e.keyCode ? e.keyCode : e.which);
//  linfo(code);
  if (code==38){
    if (history.length==0) return(false);
    if (histpos==-1) histedit=$('prompt').value;
    ++histpos;
    if (histpos>history.length-1) histpos=history.length-1;
    this.value=history[history.length-histpos-1];
    return(false);
  }else if (code==40){
    if (history.length==0 || histpos==-1) return(false);
    --histpos;
    if (histpos<0) { $('prompt').value=histedit; histpos=-1; return(false); }
    this.value=history[history.length-histpos-1];
    return(false);
  }else if (code==27){
    acdbHide();
  }
  return(true);
}

function doSendLogin(){
  if ($('login').value.length==0) return;
  var msg={0:{type:"login",user:$('login').value,pass:$('pass').value}};
  connSend(JSON.stringify(msg));
  alert('sent login');
}

function doSendCommand(){
  if ($('prompt').value.length==0) return;
  var msg={0:{type:"cmd",cmd:$('prompt').value}};
  connSend(JSON.stringify(msg));
  history.push($('prompt').value);
  $('consoleout').innerHTML+="> "+$('prompt').value+"<br/>";
  $('prompt').value="";
  histpos=-1;
}

function doSendText(){
  if ($('chatline').value.length==0) return;
  var msg={0:{type:"msg",msg:$('chatline').value}};
  connSend(JSON.stringify(msg));
  $('chat').innerHTML+="> "+$('chatline').value+"<br/>";
  $('chatline').value="";
  histpos=-1;
}



var username='';
var channel='';
var server='';
var sid='';

function getArgs(){
  var url=document.location.href;
  var i=url.indexOf("?");
  if (i==-1) { return({}); }
  url=url.substr(i+1);

  var res={};
  var args=url.split("&");
  for (i=0; i<args.length; ++i){
    var tmp=args[i].split("=");
    res[tmp[0]]=tmp[1];
  }
  return(res);
}

function getServer()
{
  var url=document.location.href;
  var i=url.indexOf("?");
  if (i==-1) { server=url; return; }

  url=url.substr(0,i);
  return(url);
}


function $(e){ return(document.getElementById(e)); }







function run(){
  getWindowSize();
  initConsole();
  initChat();
  var args=getArgs();
  
  if (!("sid" in args)) return;

  sid=args["sid"];
  channel=args["channel"];
  if (typeof channel=='undefined') channel="/";
  server=getServer();

  loaded=true;

  connStatus(doReceiveStatus);
  connListen(doReceiveData);
}

function getWindowSize(){
  if (self.innerWidth)
    { sWidth=self.innerWidth; sHeight=self.innerHeight; }
  else if (document.documentElement && document.documentElement.clientHeight)
    { sWidth = document.documentElement.clientWidth; sHeight = document.documentElement.clientHeight; }
  else if (document.body)
    { sWidth = document.body.clientWidth; sHeight = document.body.clientHeight; }
}

