/* 
 *  Ajax-based hand written recognition
 *  Copyright (C) Taku Kudo <taku@chasen.org>
 *  Used under the GNU General Public Licence.
 *  Modified by Ben K. Bullock <benkasminbullock@gmail.com>
 */

/* Show the list of kanji returned by the server for the handwritten
kanji part. There is a fixed maximum of ten or twenty characters
returned, ordered by likelihood, so it isn't necessary to have
scrolling. */

function draw_show_kanji_list (reply)
{
    var draw_result = parse_json (reply);
    if (! draw_result)
        return;
    var found_kanji = clear_found_kanji ();
    for (var k in draw_result.results) {
        create_link (found_kanji, draw_result.results[k][0]);
        append_text (found_kanji, " ");
    }
}

/* Get the position of the event. This is used to find the position of
the cursor when drawing the kanji. */

function getPosition(evt)
{
    evt = (evt) ?  evt : ((event) ? event : null);
    var left = 0;
    var top = 0;
//    var used;
    if (evt.pageX) {
	left = evt.pageX;
	top  = evt.pageY;
//	used = "pageX/Y";
    } else if (document.documentElement.scrollLeft) {
        // Internet Explorer specific.
	left = evt.clientX + document.documentElement.scrollLeft;
	top  = evt.clientY + document.documentElement.scrollTop;
	// used = "document.documentElement.scrollLeft = " + 
	//     document.documentElement.scrollLeft + " Top = " +
	//     document.documentElement.scrollTop;
    } else  {
	//DOM compliant
	left = evt.clientX + document.body.scrollLeft;
	top  = evt.clientY + document.body.scrollTop;
	// used = "document.body.scrollLeft = " + 
	//     document.body.scrollLeft + " Top = " +
	//     document.body.scrollTop;
    }
    return {x : left, y : top}; 
}

function alter_link_if_canvas ()
{
    var has_canvas = !!document.createElement('canvas').getContext;
    if (has_canvas) {
        var kanji16_link = getbyid ("kanji16-link");
        kanji16_link.href = "http://kanji.sljfaq.org/kanji16/draw-canvas.html";
    }
}

onload = function ()
{
    var drawkanji = new DrawKanji();
    check_debug ();
    alter_link_if_canvas ();
}

// main object

function DrawKanji ()
{
    var canvas = getbyid("drawkanji-canvas");
    this.canvas = canvas;
    var self = this;
    canvas.onmouseup   = function(event) { self.mouseup(event); }
    canvas.onmousedown = function(event) { self.mousedown(event); }
    canvas.onmousemove = function(event) { self.mousemove(event); }

    var clear_button = getbyid("drawkanji-clear-button");
    clear_button.onclick = function(event) { self.clearAll(); }

    var back_button = getbyid("drawkanji-back-line-button");
    back_button.onclick = function(event) { self.backLine(); }

    // Get the correct offset of the canvas relative to the browser
    // window, for correct drawing.
    var left = 0;
    var top = 0;
    for (var o = canvas; o ; o = o.offsetParent) {
	left += (o.offsetLeft - o.scrollLeft);
	top  += (o.offsetTop - o.scrollTop);
    }
    this.offsetLeft = left;
    this.offsetTop  = top;

    this.clearAll();
}

DrawKanji.prototype.clearAll = function()
{
    this.clear();
    clear_found_kanji ();
}

// Go back one line. This corresponds to the "remove last stroke"
// button at the base of the kanji drawing canvas.

DrawKanji.prototype.backLine = function()
{
    if (this.stroke_num > 0) {
	this.sequence.pop();
	this.stroke_num--;
    }
    if (this.stroke_num > 0) {
	clear (this.canvas);
	this.drawAll();
	this.sendStroke();
    } else {
	this.clearAll();
    }
}

// Reset all the variables to null states.

DrawKanji.prototype.clear = function()
{
    this.active = false;
    // The array containing the data for each line.
    this.sequence = [];
    this.point_num = 0;
    this.stroke_num = 0;
    this.prev_x = -1;
    this.prev_y = -1;
    this.resultNum = 0;
    this.resultChar = "";
    this.exampleId = 0;

    clear (this.canvas);
}

DrawKanji.prototype.sendStroke = function()
{
    var r = this.makeMessage('H');
    sendit (r, draw_show_kanji_list);
}

// End the current stroke.

DrawKanji.prototype.mouseup = function(event)
{
    if (this.active) {
        this.active = false;
        this.trace(event);
        this.finishStroke();
        this.sendStroke();
    }
}

// Add to the end of the current stroke.

DrawKanji.prototype.mousemove = function(event)
{
    this.trace(event);
}

// Start drawing a new stroke.

DrawKanji.prototype.mousedown = function(event) 
{
    this.active = true;
    this.trace(event);
    // Prevent the mousedown from triggering a drag and drop, which
    // causes drawing errors in Internet Explorer.
    if (event.preventDefault)
        event.preventDefault();
    else
        event.returnValue = false;
    return false;
}

// Reset the line drawing variables at the end of a stroke.

DrawKanji.prototype.finishStroke = function()
{
    this.active = false;
    this.point_num = 0;
    this.annotate2 (this.stroke_num);
    this.stroke_num++;
    this.prev_x = -1;
    this.prev_y = -1;
}

// Draw the entire thing again.

DrawKanji.prototype.drawAll = function()
{
    var stroke;
    var point_num;
    var l = this.offsetLeft;
    var t = this.offsetTop;
    for (stroke = 0; stroke < this.stroke_num; stroke++) {
	this.drawDot(this.sequence[stroke][0].x + l,
		     this.sequence[stroke][0].y + t);
	var cs = this.sequence[stroke];
	var o = parseInt ((this.sequence[stroke].length)/2);
//	alert (o);
	this.annotate2 (stroke);

	for (point_num=0; point_num < this.sequence[stroke].length - 1; 
	     point_num++) {
	    this.drawLine(this.sequence[stroke][point_num].x + l,
			  this.sequence[stroke][point_num].y + t,
			  this.sequence[stroke][point_num+1].x + l,
			  this.sequence[stroke][point_num+1].y + t);
	}
    }
}

// Add the number to the stroke.

DrawKanji.prototype.annotate2 = function(stroke)
{
    // Point halfway along the line where we will locate the number.
    var o = parseInt ((this.sequence[stroke].length)/2) - 1;
    // Next next point; to locate the number at a tangent to the line.
    var o2 = o+2;
    var x = this.sequence[stroke][o].x + this.offsetLeft;
    var y = this.sequence[stroke][o].y + this.offsetTop;
    var x2 = this.sequence[stroke][o2].x + this.offsetLeft;
    var y2 = this.sequence[stroke][o2].y + this.offsetTop;
    var angle;
    var xdiff = x2 - x;
    var ydiff = y2 - y;
    var seglen = Math.sqrt (xdiff*xdiff + ydiff*ydiff);
    var xoffset;
    var yoffset;
    var offsetlength = 15; // How far from the line, in px, we put the number.
    if (seglen < 1.0) {
	// Give up trying to work out what the tangent is, just throw
	// it away from the line.
//	alert ("zero");
	xoffset = offsetlength;
	yoffset = offsetlength;
    } else {
	// Use a maths trick to work out where to put the number.
	var xoffset = parseInt (- ydiff * offsetlength / seglen);
	var yoffset = parseInt (xdiff * offsetlength / seglen) - (0.5*offsetlength);
//	alert ("xoffset = "+xoffset+", yoffset = "+yoffset);
    }
    // Adjust for size of character.  
    var stroke_num = stroke+1;
    var number = document.createTextNode(stroke_num);
    var dot = document.createElement("span");
    dot.appendChild(number);
    dot.style.left = (x+xoffset)  + "px";
    dot.style.top =  (y+yoffset)  + "px";
    dot.className = "drawkanji-stroke-number";
    this.canvas.appendChild(dot);
}

DrawKanji.prototype.addPoint = function(x, y)
{
    var x2 = x - this.offsetLeft;
    var y2 = y - this.offsetTop;

    if (this.point_num == 0) 
	this.sequence[this.stroke_num] = new Array;

    this.sequence[this.stroke_num][this.point_num] = { x:x2, y:y2 };
    ++this.point_num;

    if (this.prev_x != -1) {
	this.drawLine(this.prev_x, this.prev_y, x, y);
    } else {
	this.drawDot(x, y);
    }  
    this.prev_x = x;
    this.prev_y = y;
}

DrawKanji.prototype.trace = function (event)
{
    if (! this.active) return;
    var pos = getPosition(event);
    this.addPoint(pos.x, pos.y);
}

DrawKanji.prototype.drawDot = function(x,y)
{
    var dot = document.createElement("span");
    dot.style.left = x  + "px";
    dot.style.top =  y  + "px";
    dot.className = "drawkanji-dot";
    this.canvas.appendChild(dot);
}

DrawKanji.prototype.drawLine = function(x1,y1,x2,y2) 
{
    if (x1 == x2 && y1 == y2) return;

    var x_move = x2 - x1;
    var y_move = y2 - y1;
    var x_diff = x_move < 0 ? 1 : -1;
    var y_diff = y_move < 0 ? 1 : -1;

    if (Math.abs(x_move) >= Math.abs(y_move)){
	for (var i = x_move; i != 0; i += x_diff) {
	    this.drawDot(x2 - i, y2 - Math.round(y_move * i / x_move));
	}
    } else {
	for (var i = y_move; i != 0; i += y_diff) {
	    this.drawDot(x2 - Math.round(x_move * i / y_move), y2 - i);
	}
    }
}

// Make the string to send to the CGI script

DrawKanji.prototype.makeMessage = function (c)
{
    var r = c;
    for (var i = 0; i < this.sequence.length; ++i) {
	for (var j = 0; j < this.sequence[i].length; ++j) {
	    r += (" " + this.sequence[i][j].x + " " + 
                  this.sequence[i][j].y + " " );
	}
	r += "\n";
    }
    r+= "\n\n";
    return r;
}  
