/*
    try { xmlHttp = new XMLHttpRequest(); }
    catch(e)
    {
        try { xmlHttp  = new ActiveXObject("Microsoft.XMLHTTP"); }
        catch(e)
        {
            try { xmlHttp  = new ActiveXObject("Msxml2.XMLHTTP"); }
            catch(e)
            {
                alert("Your browser doesn't support dynamic reload.");
                return;
            }
        }
    }
    */

function $(id) { return document.getElementById(id); }
function trim(str) { return str.replace("/^\s\s*/", '').replace("/\s\s*$/", ''); }
function valid(str) { if (str==undefined) return false; if (str.length==0) return false; return true;}
function isSliding(){ return $("table0").offsetLeft!=0 && $("table1").offsetLeft!=0; }
function cycleCol(el)
{
    var col = el.getAttribute("data-col");
    col++;
    col %= 31;
    el.setAttribute("data-col", col);
    if (col>16)
        col = 31-col;
    var hex = col.toString(16);
    el.style.color = "#"+hex+"0"+hex+"0"+hex+"f";
}

function onload()
{
    /*
     alert("0 -- "+navigator.appCodeName+"\n"+
          "1 -- "+navigator.appName+"\n"+
          "2 -- "+navigator.appVersion+"\n"+
          "3 -- "+navigator.platform+"\n"+
          "4 -- "+navigator.userAgent);
          */
    loadPage("fact", 0);
}

function onresize()
{
    var z = $("body").getAttribute("data-visible");
    doresize(z);
}

function loadPage(name, z)
{
    var xmlHttp = null;

    try { xmlHttp = new XMLHttpRequest(); }
    catch(e)
    {
        alert("Your browser doesn't support dynamic reload.");
        return;
    }

    xmlHttp.open('POST', name+'.table', true);

    xmlHttp.onreadystatechange =
        function ()
        {
            if (xmlHttp.readyState == 4)
            {
                if (xmlHttp.status!=0 && xmlHttp.status!=200)
                {
                    alert("ERROR[0] - HTTP request '"+name+".table': "+xmlHttp.statusText+" ["+xmlHttp.status+"]");
                    //setTimeout("loadPage('+name+')", 5000);
                    /****** invalidate ******/
                    return;
                }

                buildPage(name, xmlHttp.responseText, (z+1)%2);
                changePage(z);

                //changePage(name, xmlHttp.resposeText);
                //slideOut(name, xmlHttp.responseText);
                //displayPage(name, xmlHttp.responseText);
                //onresize(true);
            }
        };

    xmlHttp.send(null);
}


function buildPage(name, text, z)
{
    var table = $("table"+z);
    var p = table.tBodies.length==3 ? 1 : 0;

    var tbody = $("table"+z).tBodies[p];

    while (tbody.hasChildNodes())
        tbody.removeChild(tbody.lastChild);

    var lines = text.split('\n');

    if (lines.length>0)
    {
        /*
        var newe = document.createElement("span");
        newe.innerHTML = lines[0];
        var title = $("table"+z).tHead.rows[0].cells[0].childNodes[0].childNodes[1];
        title.replaceChild(newe, title.lastChild);
        */

        //var x = title.lastChild;
        //title.removeChild(title.lastChild);
        //title.appendChild(newe);

        var newe = document.createElement("span");
        newe.innerHTML = lines[0];
        var title = $("title"+z);//.innerHtml = lines[0];
        title.replaceChild(newe, title.lastChild);
    }

    var counter = 1;
    for (var i=1; i<lines.length; i++)
    {
        lines[i] = trim(lines[i]);

        if (lines[i].length==0 || lines[i][0] == '#')
            continue;

        var cols = lines[i].split(':');
        if (cols.length != 3 && cols.length !=4)
        {
            alert("Size mismatch #"+i+": '"+lines[i]+"' N(cols)="+cols.length);
            continue;
        }

        if (cols[1].substring(0, 7)=="canvas=")
        {
            var tr = document.createElement("tr");
            tr.setAttribute("class", "row");
            tr.setAttribute("style", "margin:0;padding:0;");

            var td = document.createElement("td");
            td.setAttribute("class",   "container");
            td.setAttribute("id",      "container");
            //td.setAttribute("onclick", "save();");
            td.setAttribute("colspan", "3");
            tr.appendChild(td);

            var canv = document.createElement("canvas");
            canv.setAttribute("id",     "canvas"+z);
            canv.setAttribute("width",  "1");
            canv.setAttribute("height", "1");
            canv.setAttribute("data-file", cols[1].substring(7));
            canv.setAttribute("style", "display:none;");
            td.appendChild(canv);

            var img = document.createElement("img");
            img.setAttribute("id",     "image"+z);
            img.setAttribute("width",  "1");
            img.setAttribute("height", "1");
            td.appendChild(img);

            tbody.appendChild(tr);
            continue;
        }

        var tr = document.createElement("tr");
        tr.setAttribute("class", "row");
        if (valid(cols[0]))
            tr.setAttribute("onclick", "this.style.background='#ccb'; loadPage('"+cols[0]+"',"+z+");");
        if (valid(cols[3]))
            tr.setAttribute("onclick", "this.style.background='#ccb'; loadPage('"+cols[3]+"',"+z+");");
        //tr.setAttribute("id",    cols[0]+"_row");

        var td0 = document.createElement("td");
        td0.setAttribute("class", "tcol0");
        if (valid(cols[0]))
            td0.appendChild(document.createTextNode("<"));
        tr.appendChild(td0);

        var td1 = document.createElement("td");
        td1.setAttribute("class", "tcol1");
        td1.setAttribute("width", "100%");
        tr.appendChild(td1);

        var td2 = document.createElement("td");
        td2.setAttribute("class", "tcol2");
        if (valid(cols[3]))
            td2.appendChild(document.createTextNode(">"));
        tr.appendChild(td2);

        var tab = document.createElement("table");
        tab.setAttribute("width", "100%");
        td1.appendChild(tab);

        var innertr = document.createElement("tr");
        tab.appendChild(innertr);

        var cell1 = document.createElement("td");
        cell1.setAttribute("class", "tcell1");
        //cell1.setAttribute("id",    cols[0]+"_title");
        cell1.appendChild(document.createTextNode(cols[1]));

        var cell2 = document.createElement("td");
        cell2.setAttribute("class", "tcell2");
        cell2.setAttribute("id",    "data"+counter);
        cell2.setAttribute("data-form",  cols[2]);
        cell2.appendChild(document.createTextNode("---"));

        innertr.appendChild(cell1);
        innertr.appendChild(cell2);

        tbody.appendChild(tr);

        counter++;
    }

    // ---------------------------------------

    tr = document.createElement("tr");
    tr.setAttribute("class", "row");

    td = document.createElement("td");
    td.setAttribute("id", "debug");
    td.setAttribute("colspan", "3");
    tr.appendChild(td);

    tbody.appendChild(tr);

    // ---------------------------------------

    table.setAttribute("data-file", name);
    doresize(z);
}

function doresize(z)
{
    var img  = $("image"+z);
    var canv = $("canvas"+z);
    if (img == undefined || canv == undefined)
        return;

    var W = window.innerWidth;
    var H = window.innerHeight;

    //img.width  = 1;
    //img.height = 1;

    var h = $("table"+z).offsetHeight;

    //alert(img.height+"/"+img.offsetHeight+"/"+img.parentNode.offsetHeight);

    // Be aware that this is recursive!
    img.width   = W;
    img.height += H - h;

    canv.width  = img.width;
    canv.height = img.height;

    // ------ debug -----
    $('debug').innerHTML = "";
    $('debug').innerHTML += "|W="+W +"/"+H;
    $('debug').innerHTML += "|H="+h+"/"+$("table"+z).offsetHeight;
}

var intervalSlide = null;

function changePage(z)
{
    // No page displayed yet
    if ($("table0").style.display=="none" && $("table1").style.display=="none")
    {
        $("table0").style.display="";
        $("table1").style.display="";

        $("table0").style.left=window.innerWidth+"px";
        $("table1").style.left="0px";

        $("body").setAttribute("data-visible", "1");

        doresize(1);

        refresh_text();
        refresh_graphics();
        return;
    }

    //intervalSlide = setInterval("doSlideOut("+z+")", 25);

    //var k = (z+1)%2;
    //$("table"+k).style.display="";
    //$("table"+z).style.display="";
    //$("table"+k).style.zIndex="0";
    //$("table"+z).style.zIndex="1";
    //$("table"+k).style.left=0;
    //$("table"+z).style.left=0;
    //$("table"+k).style.backgroundColor = "#ffffff";
    //$("table"+z).style.backgroundColor = "#ffffff";
    //doresize(k);
    //intervalSlide = setInterval("doSlide("+z+",1)", 50);

    $("body").setAttribute("data-visible", (z+1)%2);
    intervalSlide = setInterval("doShift("+z+")", 75);
}

function doShift(z)
{
    var W = window.innerWidth;

    var t0 = $("table0");
    var t1 = $("table1");

    var x0 = t0.offsetLeft;
    var x1 = t1.offsetLeft;

    if (/*x1<0 && x0>=0 &&*/ z==0)
    {
        x0 += W/5;
        x1 += W/5;

        if (x1>=0)
        {
            x0 = W;
            x1 = 0;

            clearInterval(intervalSlide);
        }
    }

    if (/*x0>0 && x1<=0 &&*/ z==1)
    {
        x0 -= W/5;
        x1 -= W/5;

        if (x0<=0)
        {
            x0 = 0;
            x1 = -W-1;

            clearInterval(intervalSlide);
        }
    }

    t0.style.left = parseInt(x0, 10)+"px";
    t1.style.left = parseInt(x1, 10)+"px";
}

/*
function doSlide(z, dir)
{
    var k = (z+1)%2;

    var W = window.innerWidth;

    var tz = $("table"+z);
    var tk = $("table"+k);

    var xz = tz.offsetLeft;
    var xk = tk.offsetLeft;

    var ixz = parseInt(xz, 10);
    var ikz = parseInt(xk, 10);

    ixz += dir*W/10;
    ikz -= dir*W/10;

    tz.style.left = parseInt(ixz, 10)+"px";
    tk.style.left = parseInt(ikz, 10)+"px";

    if (ixz>W/2)
    {
        clearInterval(intervalSlide);

        $("table"+k).style.zIndex="1";
        $("table"+z).style.zIndex="0";

        $("body").setAttribute("data-visible", k);
        doresize(k);

        intervalSlide = setInterval("doSlide("+z+",-1)", 50);
    }
    if (ikz>0)
    {
        clearInterval(intervalSlide);

        tz.style.left = 0;
        tk.style.left = 0;

        tz.style.display="none";
    }
}


function doSlideOut(z)
{
    var table = $("table"+z);

    var W = window.innerWidth;
    var x = table.offsetLeft;

    var ix = parseInt(x, 10);
    if (ix>W)
    {
        clearInterval(intervalSlide);

        table.style.display="none";

        z = (z+1)%2;
        table = $("table"+z);

        table.style.display="";
        table.style.left = window.innerWidth+"px";

        $("body").setAttribute("data-visible", z);
        doresize(z);

        intervalSlide = setInterval("doSlideIn("+z+")", 25);
        return;
    }

    ix += W/10;
    table.style.left=ix+"px";
}

function doSlideIn(z)
{
    var table = $("table"+z);

    var W = window.innerWidth;
    var x = table.offsetLeft;

    var ix = parseInt(x, 10);

    ix -= W/10;
    if (ix<0)
        ix = 0;

    table.style.left=ix+"px";

    if (ix<=0)
    {
        clearInterval(intervalSlide);
        return;
    }
}
*/

function refresh_text()
{
    var z=$("body").getAttribute("data-visible");
    var table = $("table"+z);

    // Is sliding or no file defined?
    var fname = table.getAttribute("data-file");
    if (isSliding() || !valid(fname))
    {
        setTimeout("refresh_text()", 1000);
        return;
    }

    var xmlHttp = null;

    try { xmlHttp = new XMLHttpRequest(); }
    catch(e)
    {
        alert("Your browser doesn't support dynamic reload.");
        return;
    }

    xmlHttp.open('POST', fname+'.txt', true);

    xmlHttp.onreadystatechange =
        function ()
        {
            if (xmlHttp.readyState == 4)
            {
                if (xmlHttp.status!=0 && xmlHttp.status!=200)
                {
                    alert("ERROR[1] - HTTP request '"+fname+".txt': "+xmlHttp.statusText+" ["+xmlHttp.status+"]");
                    setTimeout("refresh_text()", 10000);
                    return;
                }

                if (!isSliding())
                {
                    cycleCol($("ldot"+z));
                    update_text(fname, xmlHttp.responseText);
                }
                setTimeout("refresh_text()", 3000);
            }
        };

    xmlHttp.send(null);
}

function strike(e, status)
{
    if (!e)
        return;

    if (!status)
        e.style.textDecoration="line-through";
    else
        e.style.textDecoration="";
}

function gray(id, str)
{
    var e = $(id);
    if (!e)
        return;

    if (valid(str))
    {
        e.style.color="#000";
        e.style.textDecoration="";
    }
    else
    {
        e.style.color="#daa";
        e.style.textDecoration="line-through";
    }

}

var date0 = null;

function update_text(fname, result)
{
    var z=$("body").getAttribute("data-visible");
    var table = $("table"+z);

    if (table.getAttribute("data-file") != fname)
        return;

    var tokens = result.split('\n');

    // ----------------------------------------------------

    var  time = $("reporttime"+z);
    var ltime = $("localtime"+z);

    var date1 = new Date();

    if (tokens[0].length!=13)
    {
        if (date0 != null)
            strike(time, date0.getTime()+60000>date1.getTime());
        // FIXME: Reset display to "---" values -- no connection
        return;
    }

    var date2 = new Date();
    date2.setTime(tokens[0]);

    strike(time, date2.getTime()+60000>date1.getTime());

    date0 = date2;

    time.innerHTML =
        "&#8226;&nbsp;"+date0.toUTCString()+"&nbsp;&#8226;";//getUTCFullYear()+"/"+date0.getUTCMonth()+"/"+date0.getUTCDate()+" "+date0.getUTCHours()+":"+date0.getUTCMinutes()+":"+date0.getUTCSeconds()+"."+date0.getUTCMilliseconds();
    ltime.innerHTML =
        "&#8226;&nbsp;"+date1.toLocaleString()+"&nbsp;&#8226;";//ISOlocalDateStr();//ltoString();

    // ----------------------------------------------------

    var p = table.tBodies.length==3 ? 1 : 0;
    var tbody = table.tBodies[p];

    for (var line=1; line<tokens.length; line++)
    {
        var c = tbody.rows[line-1].cells[1];
        if (c == undefined)
            continue;

        var e = c.childNodes[0].rows[0].cells[1];
        if (e == undefined)
            continue;

        var form = e.getAttribute("data-form");
        if (form==undefined)
            continue;

        var cols = tokens[line].split('\t');
        for (var col=1; col<cols.length; col++)
            form = form.replace("\$"+(col-1), cols[col].length==0 ? "--" : cols[col]);

        if (cols.length<=1)
            form = "---";

        var newe = document.createElement("div");
        newe.innerHTML = form;
        e.replaceChild(newe, e.lastChild);

        e.parentNode.parentNode.parentNode.parentNode.style.background=cols[0];
    }
}

// http://billmill.org/static/canvastutorial/index.html
// http://www.netmagazine.com/tutorials/learning-basics-html5-canvas
// http://www.alistapart.com/articles/responsive-web-design/

function refresh_graphics()
{
    var z = $("body").getAttribute("data-visible");

    var canvas = $("canvas"+z);

    // Is sliding or no data file defined?
    var fname = canvas==null ? "" : canvas.getAttribute("data-file");
    if (isSliding() || !valid(fname))
    {
        setTimeout("refresh_graphics()", 1000);
        return;
    }

    var xmlHttp = null;

    try { xmlHttp = new XMLHttpRequest(); }
    catch(e)
    {
        alert("Your browser doesn't support dynamic reload.");
        return;
    }

    xmlHttp.open('POST', fname, true);
    xmlHttp.onload =
        function ()
        {
            if (xmlHttp.readyState == 4)
            {
                if (xmlHttp.status!=0 && xmlHttp.status!=200)
                {
                    alert("ERROR[2] - Request '"+fname+"': "+xmlHttp.statusText+" ["+xmlHttp.status+"]");
                    setTimeout("refresh_text()", 10000);
                    //****** invalidate ******
                    return;
                }

                if (!isSliding())
                {
                    cycleCol($("rdot"+z));
                    process_eventdata(xmlHttp.responseText);
                }
                setTimeout("refresh_graphics()", 5000)
            }
        };

    xmlHttp.send(null);
}


function hueToRGB(hue)
{
    hue /= 3;
    hue %= 6;

    if (hue<1) return parseInt(255*hue,     10);
    if (hue<3) return parseInt(255,         10);
    if (hue<4) return parseInt(255*(4-hue), 10);

/*
    if (hue<1*5/4) return parseInt(255*hue*4/5);
    if (hue<2*5/4) return parseInt(255);
    if (hue<3*5/4) return parseInt(255*(3*5/4-hue)*4/5);
*/
/*
    if (hue<1.5) return parseInt(255*hue/1.5);
    if (hue<3.0) return parseInt(255);
    if (hue<4.5) return parseInt(255*(4.5-hue)/1.5);
*/
    return 0.
}

function hueToHex(flt)
{
    var s = hueToRGB(flt).toString(16);
    return s.length==2 ? s : "0"+s;
}

function HLStoRGB(hue)
{
    hue *= 14;

    var sr = hueToHex(20-hue);
    var sg = hueToHex(14-hue);
    var sb = hueToHex(26-hue);

    return sr+sg+sb;
}


function color(col)
{
    if (col==65533)
        col = 0;

    var hue = col/128;
    return HLStoRGB(hue);
}

function toHex(str, idx)
{
    var ch = str[idx].toString(16);
    return ch.length==2 ? ch : "0"+ch;
}

function drawPix(x, y, col)
{
    var z = $("body").getAttribute("data-visible");
    var canv = $("canvas"+z);

    var cw = canv.width;
    var ch = canv.height;

    var w = Math.min(cw/28, ch/28);

    var ctx  = canv.getContext("2d");

    ctx.beginPath();
    ctx.arc(x*w*2+cw/2, y*w*2+ch/2, w, 0, Math.PI*2, true);
    ctx.lineWidth = 0;
    ctx.fillStyle = "#"+color(col);
    ctx.fill();
    ctx.closePath();
}
function drawCam(data)
{
    drawPix(0, 0, data.charCodeAt(0));

    var gsSin60 = Math.sqrt(3)/2;

    var cnt = 1;
    for (var ring=1; ring<=7; ring++)
    {
        for (var s=0; s<6; s++)
        {
            for (var i=1; i<=ring; i++)
            {
                var x=0.;
                var y=0.;

                switch (s)
                {
                case 0: x = ring-i*0.5;    y = i*gsSin60;         break;
                case 1: x = ring*0.5-i;    y = ring*gsSin60;      break;
                case 2: x = -(ring+i)*0.5; y = (ring-i)*gsSin60;  break;
                case 3: x = 0.5*i-ring;    y = -i*gsSin60;        break;
                case 4: x = i-ring*0.5;    y = -ring*gsSin60;     break;
                case 5: x = (ring+i)*0.5;  y = (-ring+i)*gsSin60; break;
                }

                if (Math.sqrt(x*x+y*y)>6.7)
                    continue;
                if (ring==7 && i==6 && s==0)
                    continue;
                if (ring==7 && i==1 && s==1)
                    continue;
                if (ring==7 && i==6 && s==3)
                    continue;
                if (ring==7 && i==1 && s==4)
                    continue;

                // Rotate by 60deg
                var px = gsSin60*x - 0.5*y;
                var py = gsSin60*y + 0.5*x;

                drawPix(px, py, data.charCodeAt(cnt));
                cnt++;
            }
        }
    }
}

function drawCamLegend(canv)
{
    var cw = canv.width;
    var ch = canv.height;

    var ctx = canv.getContext("2d");

    ctx.font         = "8pt Arial";
    ctx.textAlign    = "right";
    ctx.textBaseline = "top";

    ctx.strokeStyle = "#"+color(0);
    ctx.strokeText("-2.0V", cw-5, 135);

    ctx.strokeStyle = "#"+color(16);
    ctx.strokeText("-1.5V", cw-5, 120);

    ctx.strokeStyle = "#"+color(32);
    ctx.strokeText("-1.0V", cw-5, 105);

    ctx.strokeStyle = "#"+color(48);
    ctx.strokeText("-0.5V", cw-5, 90);

    ctx.strokeStyle = "#"+color(64);
    ctx.strokeText("0V", cw-5, 70);

    ctx.strokeStyle = "#"+color(80);
    ctx.strokeText("0.5V", cw-5, 50);

    ctx.strokeStyle = "#"+color(86);
    ctx.strokeText("1.0V", cw-5, 35);

    ctx.strokeStyle = "#"+color(102);
    ctx.strokeText("1.5V", cw-5, 20);

    ctx.strokeStyle = "#"+color(127);
    ctx.strokeText("2.0V", cw-5, 5);
}

function drawGraph(canv, data)
{
    var cw = canv.width;
    var ch = canv.height;

    var ctx = canv.getContext("2d");

    var dx = 15;
    var dy = 15;

    var dw =  5;

    var nx = 20;
    var ny = 10;

    var w = cw-2*dx;
    var h = ch-2*dy;

    ctx.strokeStyle = "#808080";

    ctx.beginPath();
    ctx.moveTo(dx, ch-dy-data.charCodeAt(0)/128*h);
    for (var i=1; i<data.length; i++)
        ctx.lineTo(dx+w/data.length*i, ch-dy-data.charCodeAt(i)/128*h);
    ctx.lineTo(dx+w, ch-dy);
    ctx.lineTo(dx,   ch-dy);
    ctx.fillStyle = "#"+color(100);
    ctx.fill();
    ctx.stroke();
    ctx.closePath();

    ctx.strokeStyle = "#000000";

    ctx.beginPath();

    ctx.moveTo(dx,    dy);
    ctx.lineTo(dx,    ch-dy);
    ctx.lineTo(cw-dx, ch-dy);

    for (var i=0; i<nx; i++)
    {
        ctx.moveTo(dx+w/nx*i, ch-dy-dw);
        ctx.lineTo(dx+w/nx*i, ch-dy+dw);
    }
    for (var i=0; i<ny; i++)
    {
        ctx.moveTo(dx-dw, dy+h/ny*i);
        ctx.lineTo(dx+dw, dy+h/ny*i);
    }
    ctx.stroke();
    ctx.closePath();
}

function process_eventdata(result)
{
    if (result.length!=160)
        return;

    var z = $("body").getAttribute("data-visible");
    var canv = $("canvas"+z);
    if (canv == undefined)
        return;

    var ctx = canv.getContext("2d");
    ctx.clearRect(0, 0, canv.width, canv.height);

    drawGraph(canv, result);

    drawCam(result);
    drawCamLegend(canv);

    $("image"+z).src = canv.toDataURL("image/png");
}

/*
function save()
{
    var z = $("body").getAttribute("data-visible");

    var canvas = $("canvas"+z);
    var img    = canvas.toDataURL("image/png");

    img = img.replace("image/png", "image/octet-stream");

    document.location.href = img;
}
*/
window['onload'] = onload;
