var debug = false;

var fps_label = false;
var draw_buffers = new Array();
var paused_draw_buffers = false;
var paused_animation = false;
var frame_timings = new Array();

var render_animation = false;
var animation_current_frame = 0;
var animation_duration = 20;
var animation_fps = 10;
var animation_max_frames = animation_duration*animation_fps;
var refresh_rate = 1000*animation_duration/animation_max_frames; /*ms delay*/

var extractInfo = false;
var logo_design_info = new Array();

function sLogoExtractODG(){
    var tt = document.createElement("textarea");
    tt.style.font = "10px arial";
    tt.style.color = "black";
    document.body.appendChild(tt);

    function odg($t){
	tt.appendChild(document.createTextNode($t+"\n"));
    }
    
    /**
       Example of a document with a rectangle and triangle:

       <draw:rect draw:style-name="gr1" draw:text-style-name="P1" draw:layer="layout" svg:width="3.175cm" svg:height="2.54cm" svg:x="4.175cm" svg:y="4.175cm">
       <text:p />
       </draw:rect>

       <draw:polygon draw:style-name="gr1" draw:text-style-name="P1" draw:layer="layout" svg:width="9.524cm" svg:height="8.889cm" svg:x="3.54cm" svg:y="9.255cm" svg:viewBox="0 0 9525 8890" draw:points="1270,0 9525,5080 0,8890">
       <text:p />
       </draw:polygon>

    **/

    odg("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
    odg("<office:document-content xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\" xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\" xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\" xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\" xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\" xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\" xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\" xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\" xmlns:math=\"http://www.w3.org/1998/Math/MathML\" xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\" xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\" xmlns:ooo=\"http://openoffice.org/2004/office\" xmlns:ooow=\"http://openoffice.org/2004/writer\" xmlns:oooc=\"http://openoffice.org/2004/calc\" xmlns:dom=\"http://www.w3.org/2001/xml-events\" xmlns:xforms=\"http://www.w3.org/2002/xforms\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:smil=\"urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0\" xmlns:anim=\"urn:oasis:names:tc:opendocument:xmlns:animation:1.0\" xmlns:rpt=\"http://openoffice.org/2005/report\" xmlns:of=\"urn:oasis:names:tc:opendocument:xmlns:of:1.2\" xmlns:rdfa=\"http://docs.oasis-open.org/opendocument/meta/rdfa#\" xmlns:field=\"urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0\" office:version=\"1.2\">");
    odg("<office:scripts />");
    odg("<office:automatic-styles>");
    odg("<style:style style:name=\"dp1\" style:family=\"drawing-page\" />");
    odg("</office:automatic-styles>");
    odg("<office:body>");
    odg("<office:drawing>");
    odg("<draw:page draw:name=\"page1\" draw:style-name=\"dp1\" draw:master-page-name=\"Default\">");
    for(var i=0; i<logo_design_info.length; i++){
	odg(logo_design_info[i]);
    }
    odg("</draw:page>");
    odg("</office:drawing>");
    odg("</office:body>");
    odg("</office:document-content>");

}

function odg_PtConv(pixPos,doMM){
    if(doMM==true){ return parseInt(50*pixPos); }
    return (odg_PtConv(pixPos,true)/1000)+"cm";
}

function odg_Rectangle(xywh){
    var rStr = "<draw:rect draw:style-name=\"gr1\" draw:text-style-name=\"P1\" draw:layer=\"layout\" svg:width=\""+
	odg_PtConv(xywh[2])+"\" svg:height=\""+odg_PtConv(xywh[3])+"\" svg:x=\""+
	odg_PtConv(xywh[0])+"\" svg:y=\""+odg_PtConv(xywh[1])+"\"><text:p /></draw:rect>";
    logo_design_info.push(rStr);
}
function odg_Triangle(xpoints,ypoints){
    var xminmax = new Array(xpoints[0], xpoints[0]);
    var yminmax = new Array(ypoints[0], ypoints[0]);
    for(var i=1; i<3; i++){
	if(xpoints[i] < xminmax[0]){ xminmax[0] = xpoints[i]; }
	if(xpoints[i] > xminmax[1]){ xminmax[1] = xpoints[i]; }
	if(ypoints[i] < yminmax[0]){ yminmax[0] = ypoints[i]; }
	if(ypoints[i] > yminmax[1]){ yminmax[1] = ypoints[i]; }
    }
    var tStr = "<draw:polygon draw:style-name=\"gr1\" draw:text-style-name=\"P1\" draw:layer=\"layout\" svg:width=\""+
	odg_PtConv(xminmax[1]-xminmax[0]-0.01)+"\" svg:height=\""+
	odg_PtConv(yminmax[1]-yminmax[0]-0.01)+"\" svg:x=\""+
	odg_PtConv(xminmax[0])+"\" svg:y=\""+
	odg_PtConv(yminmax[0])+"\" svg:viewBox=\"0 0 "+
	odg_PtConv(xminmax[1]-xminmax[0], true)+" "+
	odg_PtConv(yminmax[1]-yminmax[0], true)+"\" draw:points=\"";
    for(var i=0; i<3; i++){  
	if(i!=0){ tStr += " "; }
	tStr += odg_PtConv(xpoints[i], true)+","+odg_PtConv(ypoints[i], true);
    }
    tStr += "\"><text:p /></draw:polygon>";
    logo_design_info.push(tStr);
}

function sSwapBuffers(){
    if(animation_current_frame < animation_max_frames){
	/* still rendering */
    } else {
	if(animation_current_frame == animation_max_frames){
	    /* hide the initial still frame */
	    draw_buffers[2].style.display = "none";
	    draw_buffers[2].style.visibility = "hidden";
	} else if(paused_animation == true){ return; }

	draw_buffers[0].style.display = "none";
	draw_buffers[0].style.visibility = "hidden";
	draw_buffers[1].style.display = "block";
	draw_buffers[1].style.visibility = "visible";
    }
    var b = draw_buffers.shift();
    draw_buffers.push(b);
}

function sOnd(theVal){
    /* value assumed to be a fraction 0..1 */
    return (1.0-Math.cos(theVal*2.0*Math.PI))/2.0;
}

function sDrawFrame(theGraph, theTime){
    /* the drawing function... */
    sDrawFrame_sinusoidLogo(theGraph, theTime);
}

function geometry_rotate(radAngle, aroundAxisStr, center3dPosition, point3dPosition){
    var X = 0; var Y = 1; var Z = 2;
    var normalizedPoint = Array(point3dPosition[X]-center3dPosition[X],
				point3dPosition[Y]-center3dPosition[Y],
				point3dPosition[Z]-center3dPosition[Z]);
    var newPoint = Array();
    if(aroundAxisStr == "z"){
	newPoint[X] = Math.cos(radAngle)*normalizedPoint[X] - Math.sin(radAngle)*normalizedPoint[Y]
	    + center3dPosition[X];
	newPoint[Y] = Math.sin(radAngle)*normalizedPoint[X] + Math.cos(radAngle)*normalizedPoint[Y]
	    + center3dPosition[Y];
    }
    else {
	/* Didnt bother to support other axis */
	document.body.appendChild(capsule("div",echo("Unknown rotation axis ["+aroundAxisStr+"]")));
    }
    return newPoint;
}

function sDrawFrame_sinusoidLogo(theGraph, theTime){

    var width = 320;
    var height = 240;

    var logo_roll_amp = Math.PI/32;
    var logo_roll_offset = Math.PI*3/8-(0*logo_roll_amp/2);
    var logo_roll_speed = 0*0.1;

    var anim_sond = sOnd(theTime/animation_duration);

    var wave_x_offset = width/4;
    var wave_y_offset = height/2;
    var wave_length = width/2;
    var wave_precision = 16+8;
    var wave_amp = height/4;
    var diagonal_amp = 1.3*wave_amp*(1-anim_sond);
    var diagonal_curvature = 4;
    var ripples_amp = new Array(wave_amp*0.8,
				wave_amp*0.4);

    var ripples_freq = new Array(1,
				 3);
    var ripples_speed = new Array(-0.1*0,
				  2*0.5);

    theGraph.clear();
    var xPos = new Array();
    var yPos = new Array();

    /* for extracting the logo elements positions, only once */
    if(extractInfo && logo_design_info.length > 0) extractInfo = false;
	
    /* generate sine wave */
    for(var i=0; i<=wave_precision; i++){
	var x = i/wave_precision;
	/* line point A (along the x axis) */
	xPos.push(wave_x_offset + wave_length*x);
	yPos.push(wave_y_offset - diagonal_amp*Math.pow(x, diagonal_curvature));

	/* line point B (wave point) */
	xPos.push(wave_x_offset + wave_length*x);
	var wave_y = wave_y_offset;

	/* diagonal */   
	wave_y += diagonal_amp*Math.pow(x, diagonal_curvature);

	/* ripples in the wave */
	for(var r=0; r<ripples_amp.length; r++){
	    var theRipple = ripples_amp[r]*Math.sin(ripples_freq[r]*x*2*Math.PI 
						    + 2*Math.PI*theTime*ripples_speed[r]);
	    if(r > 0){ wave_y += theRipple*x*anim_sond; }
	    else { wave_y += theRipple; }
	}
	yPos.push(wave_y);
    }

    /* rotate the logo's points */
    for(var i=0; i<xPos.length; i++){
	var fullroll = logo_roll_offset + logo_roll_amp*Math.sin(logo_roll_speed*2*Math.PI*theTime);
	var new_xy = geometry_rotate(fullroll, "z", 
				     Array(width/2, height/2, 0), 
				     Array(xPos[i], yPos[i], 0));
	xPos[i] = parseInt(new_xy[0]);
	yPos[i] = parseInt(new_xy[1]);
    }

    for(var i=0; i<2*wave_precision; i+=2){

	/**
	 *  sinusoid logo lines design
	 */
	
	var rightOne = 1;
	if(xPos[i+0] > xPos[i+1]){ rightOne = 0; }
	var leftOne = 1-rightOne;

	var leftPointOut = 2;
	var leftPointIn = 1;
	var pointSize = 2*leftPointIn+1;	
	var rightPointSize = pointSize-2;


	theGraph.setColor("#d0d0d0");
	var lineXpoints = new Array(xPos[i+leftOne]-leftPointIn,xPos[i+rightOne],xPos[i+leftOne]+rightPointSize);
	var lineYpoints = new Array(yPos[i+leftOne]-leftPointIn,yPos[i+rightOne],yPos[i+leftOne]+rightPointSize);
	theGraph.fillPolygon(lineXpoints, lineYpoints);
	
	theGraph.setColor("#ffffff");
	var QuadXYWH = new Array(xPos[i+leftOne]-leftPointIn,
				 yPos[i+leftOne]-leftPointIn,
				 pointSize, pointSize);

	theGraph.fillRect(QuadXYWH[0], QuadXYWH[1], QuadXYWH[2], QuadXYWH[3]);

	if(extractInfo){
	    odg_Triangle(lineXpoints, lineYpoints);
	    odg_Rectangle(QuadXYWH);
	}
    }
    theGraph.paint();

    if(extractInfo){
	sLogoExtractODG();
    }
}

function sLabel(theText){
    while(fps_label.hasChildNodes()){ fps_label.removeChild(fps_label.firstChild); }
    if(theText != false){
	fps_label.appendChild(capsule("div", echo(theText)));
    }
}

function sDrawBuffer(theBuffer){
    
    if(!theBuffer.jsGraph){ 
	alert("no jsGraph attached to the drawing buffer supplied");
	draw_buffers = false; 
    } else {
	if(animation_current_frame < animation_max_frames){
	    sLabel("Animation: "
		   +parseInt(100*animation_current_frame/animation_max_frames)
		   +"%");
	    var theTime = animation_duration*animation_current_frame/animation_max_frames;
	    sDrawFrame(theBuffer.jsGraph, theTime);
	} else {
	    /* Whole animation is drawn, noop */
	}
    }
}

function sPause(playInstead){
    
    if(playInstead && playInstead == true){
	paused_animation = true;
    } else {
	paused_animation = false;
    }
}

function sMainLoop(){
    if(fps_label && animation_current_frame <= animation_max_frames){ 
	var d = new Date();
	frame_timings.push(d.getTime());
	while(frame_timings.length > 10){ frame_timings.shift(); }
	var avgFPS = 1.0/((frame_timings[frame_timings.length-1]-frame_timings[0])/(1000*frame_timings.length));
    }

    if(paused_animation == false || 
       animation_current_frame < animation_max_frames){
	sDrawBuffer(draw_buffers[1]);
    }

    animation_current_frame++;

    if(render_animation == false){
	/* draw only once */
	setTimeout("sSwapBuffers();", 1);
	sLabel(false);
	if(false){
	    var a = document.createElement("a");
	    fps_label.appendChild(a);
	    a.appendChild(echo("Animate Logo"));
	    a.href = "javascript:void(0);";
	}
    } else {
	/* continuous animation */
	var curRefresh = refresh_rate;
 	if(paused_animation == true || animation_current_frame < 5){ curRefresh = 200; }
	else if(animation_current_frame < animation_max_frames){ curRefresh = 10; }
	setTimeout("sSwapBuffers();setTimeout('sMainLoop()',1);", curRefresh);
    }
}

function sResize(){
    var winWidth = 800;
    var winHeight = 480;
}

function sInit(){

    /* reset elements if needed */
    var f;
    f = document.getElementById("fpsLabel");
    if(f){ f.nodeParent.removeChild(f); }
    f = document.getElementById("drawingboard_table");
    if(f){ f.nodeParent.removeChild(f); }

    document.body.style.padding = "0px";
    document.body.style.position = "relative";

    var fpsLabel = document.createElement("label");
    document.body.appendChild(fpsLabel);
    fps_label = fpsLabel;
    fpsLabel.id = "fpslabel";
    fpsLabel.style.position = "absolute";
    fpsLabel.style.left = "auto";
    fpsLabel.style.right = "0px";
    fpsLabel.style.top = "0px";
    fpsLabel.style.bottom = "auto";

    /* maintable: document structure */
    var t = document.createElement("table");
    document.body.appendChild(t);
    t.id = "drawingboard_table";
    t.style.height = "100%";
    t.style.margin = "auto";
    t.border = "0";
    t.cellPadding = "0";
    t.cellSpacing = "0";
    var td = t.insertRow(-1).insertCell(-1);
    td.vAlign = "middle";
    
    var drawBoard = document.createElement("div");
    td.appendChild(drawBoard);
    drawBoard.id = "drawing_board";
    drawBoard.style.position = "relative";
    drawBoard.style.width = "320px";
    drawBoard.style.height = "240px";
    
    for(var i=0; i<animation_max_frames; i++){
	var e = document.createElement("div");
	drawBoard.appendChild(e);
	e.id = "drawbuffer_"+i;
	e.style.position = "relative";
	if(i!=1){
	    /**
	     *  note that frame i==0:display, i==1:render, i>1:standby buffers
	     *  We first render on frame 1 (not zero) then swap it to display it
	     */
	    e.style.display = "none";
	    e.style.visibility = "hidden";
	}
	e.style.width = "320px";
	e.style.height = "240px";
	e.jsGraph = new jsGraphics("drawbuffer_"+i);
	e.jsGraph.setPrintable(false);
	draw_buffers.push(e);
    }

    sResize();

    setTimeout("sMainLoop();", 1);

}

