var mousex = 0;
var mousey = 0;
var OutlineColor = "#FF0D0D";
var PerspectiveColor = "#FFFF0D";

////////////////////////////////////

function trackMouse(e)
{
    if (!e)
    var e = window.event||window.Event;
    //var e = window.event || e;
    //var e=(!e)?window.event:e;//IE:Moz
    //var e = (window.event) ? window.event : evt;
    //if (!e) var e = window.event;

    if (e.pageX || e.pageY)
    {
      mousex = e.pageX;
      mousey = e.pageY;
    }
    else if (e.clientX || e.clientY)
    {
      mousex = e.clientX + document.body.scrollLeft;
      mousey = e.clientY + document.body.scrollTop;
    }
}

//////////////////////////////////////

function startMouseTracking()
{
    var bodyElement = document.getElementsByTagName("body");
    if(bodyElement.length == 1)
    {
        bodyElement = bodyElement[0];
    }
    else
    {
        setTimeout("startMouseTracking();", 500);
        return false;
    }
	try
	{	
		bodyElement.addEventListener("mousemove", trackMouse, false);
	}
	catch(err)
	{
		try
		{
			bodyElement.attachEvent("onmousemove", trackMouse);
		}
		catch(err2)
		{
		}
	}
}

/////////////////////////////////////

function ImageClick()
{
    // Update the X offset
    //var offsetX = document.getElementById("ctl00_Main_divCanvas").offsetLeft;
    var offsetX = findPosX(document.getElementById("Canvas"));
    // create the Y offset
    //var offsetY = document.getElementById("ctl00_Main_divCanvas").offsetTop;
    var offsetY = findPosY(document.getElementById("Canvas"));
       
    // Get the x and y coordinates
    x = (mousex - offsetX);
    y = (mousey - offsetY);
    
    //are we in outline mode?
    if(SelectedTool == "Outline")
    {
        SelectedRegion.OutlinePointsX[SelectedRegion.OutlinePointsX.length] = x;
        SelectedRegion.OutlinePointsY[SelectedRegion.OutlinePointsY.length] = y;
        SelectedRegion.isSaved = false;
    }
    
    //are we in perspective mode?
    if(SelectedTool == "Perspective")
    {
        var index = SelectedRegion.PerspectivePointsX.length;
        if(index > 3)
        {
            index = 3;
        }
        SelectedRegion.PerspectivePointsX[index] = x;
        SelectedRegion.PerspectivePointsY[index] = y;
        SelectedRegion.isSaved = false;
    }
    
    if(!jg)
    {
        jg = new jsGraphics(document.getElementById("Canvas"));
        jg.setColor(OutlineColor);
    }
    RefreshImage();
    return false;
}

/////////////////////////////////////

function RefreshImage()
{
    jg.clear();
    
    switch(SelectedTool)
    {
        case "Outline":
            //alert("about to draw o");
            jg.setColor(OutlineColor);
            if(SelectedRegion.OutlinePointsX.length > 0)
            {
                jg.drawEllipse(SelectedRegion.OutlinePointsX[0]-2,SelectedRegion.OutlinePointsY[0]-2,4,4);
                if(SelectedRegion.OutlinePointsX.length > 1)
                {
                    jg.drawPolygon(SelectedRegion.OutlinePointsX, SelectedRegion.OutlinePointsY);
                }
                jg.paint();
            }
            break;
        case "Perspective":
            //alert("about to draw p");
            jg.setColor(PerspectiveColor);
            if(SelectedRegion.PerspectivePointsX.length > 0)
            {
                jg.drawEllipse(SelectedRegion.PerspectivePointsX[0]-2,SelectedRegion.PerspectivePointsY[0]-2,4,4);
                if(SelectedRegion.PerspectivePointsX.length > 1)
                {
                    jg.drawPolygon(SelectedRegion.PerspectivePointsX, SelectedRegion.PerspectivePointsY);
                }
            }
            jg.paint();
            /*
            var point3D = new Point3D(); //Will be actual 2D drawing points
            
            // Set the zoom factor
            //(image width / 1.5 ?) for now lets just hardcode 460
            var zoom = 460;
            
            // Set Camera Z
            var anchorPoint = new Point3D();
            anchorPoint.Z = -1;
            var cameraZ = -(((anchorPoint.X - origin3D.X) * zoom) / origin3D.X) + anchorPoint.Z;
            CameraPos.X = origin3D.X;
            CameraPos.Y = origin3D.Y;
            CameraPos.Z =  cameraZ; 
            
            // Apply rotations
            verts = Translate(verts, origin3D, new Point3D());
            verts = RotateX(verts, xRotation); //The order of these
            verts = RotateY(verts, yRotation); //rotations is the source
            verts = RotateZ(verts, zRotation); //of Gimbal Lock
            verts = Translate(verts, new Point3D(), origin3D);
            
            // Convert 3D to 2D points
            var vec = new Point3D();
            for (i = 0; i < 4; i++) // point3D.length; i++)
            {
                vec = verts[i];
                if (vec.Z - CameraPos.Z >= 0)
                {
                    point3D[i].X = (-(vec.X - CameraPos.X) / (-0.1) * zoom) + origin.X;
                    point3D[i].Y = ((vec.Y - CameraPos.Y) / (-0.1) * zoom) + origin.Y;
                }
                else
                {
                    tmpOrigin.X = ((origin3D.X - CameraPos.X) / (origin3D.Z - CameraPos.Z) * zoom) + origin.X;
                    tmpOrigin.Y = (-(origin3D.Y - CameraPos.Y) / (origin3D.Z - CameraPos.Z) * zoom) + origin.Y;

                    point3D[i].X = ((vec.X - CameraPos.X) / (vec.Z - CameraPos.Z) * zoom + origin.X);
                    point3D[i].Y = (-(vec.Y - CameraPos.Y) / (vec.Z - CameraPos.Z) * zoom + origin.Y);

                    point3D[i].X = point3D[i].X;
                    point3D[i].Y = point3D[i].Y;
                }
            }
            
            // Something with drawing bounds
            
            
            // Draw Poly using 2D points
            // now convert our drawing points to an X and a Y array
            arrX = [];
            arrY = [];
            for(j = 0; j < 4; j++)
            {
                arrX[j] = point3D[j].X;
                arrY[j] = point3D[j].Y;
            }
            jg.drawPolygon(arrX, arrY);
            jg.paint();
            */
            break;
        
    }
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
///                                                                                                ///
///                                Perspective Math (3D stuff)                                     ///
///                                                                                                ///
//////////////////////////////////////////////////////////////////////////////////////////////////////

var verts = []; // Each vert is a Point3D
var xRotation = 0; // degrees
var yRotation = 0; // degrees
var zRotation = 0; // degrees
var origin = new Point();  // center of the outline.
var origin3D = new Point3D();  // center of something, the perspective i think
var outlinePoints = []; // array of 2D points
var TransformedPoints = []; // each point is a Point (2D)
var CameraPos = new Point3D();

function RotateX(point3D, degrees) // returns a Point3D
{
    //Here we use Euler's matrix formula for rotating a 3D point x degrees around the x-axis

    //[ a  b  c ] [ x ]   [ x*a + y*b + z*c ]
    //[ d  e  f ] [ y ] = [ x*d + y*e + z*f ]
    //[ g  h  i ] [ z ]   [ x*g + y*h + z*i ]

    //[ 1    0        0   ]
    //[ 0   cos(x)  sin(x)]
    //[ 0   -sin(x) cos(x)]

    var cDegrees = (Math.PI * degrees) / 180.0; //Convert degrees to radian for .Net Cos/Sin functions
    var cosDegrees = Math.cos(cDegrees);
    var sinDegrees = Math.sin(cDegrees);

    var y = (point3D.Y * cosDegrees) + (point3D.Z * sinDegrees);
    var z = (point3D.Y * -sinDegrees) + (point3D.Z * cosDegrees);

    p3 = new point3D();
    p3.X = point3D.X;
    p3.Y = y;
    p3.Z = z;
    return p3;
}

function RotateY(point3D, degrees)  // returns a Point3D
{
    //Y-axis

    //[ cos(x)   0    sin(x)]
    //[   0      1      0   ]
    //[-sin(x)   0    cos(x)]

    var cDegrees = (Math.PI * degrees) / 180.0; //Radians
    var cosDegrees = Math.Cos(cDegrees);
    var sinDegrees = Math.Sin(cDegrees);

    var x = (point3D.X * cosDegrees) + (point3D.Z * sinDegrees);
    var z = (point3D.X * -sinDegrees) + (point3D.Z * cosDegrees);

    p3 = new point3D();
    p3.X = x;
    p3.Y = point3D.Y;
    p3.Z = z;
    return p3;
}

function RotateZ(point3D, degrees) // Returns a Point3D
{
    //Z-axis

    //[ cos(x)  sin(x) 0]
    //[ -sin(x) cos(x) 0]
    //[    0     0     1]

    var cDegrees = (Math.PI * degrees) / 180.0; //Radians
    var cosDegrees = Math.Cos(cDegrees);
    var sinDegrees = Math.Sin(cDegrees);

    var x = (point3D.X * cosDegrees) + (point3D.Y * sinDegrees);
    var y = (point3D.X * -sinDegrees) + (point3D.Y * cosDegrees);

    p3 = new point3D();
    p3.X = x;
    p3.Y = y;
    p3.Z = point3D.Z;
    return p3;
}

function Translate(points3D, oldOrigin, newOrigin) // Returns a Point3D
{
    //Moves a 3D point based on a moved reference point
    var difference = new Point3D();
    difference.X = newOrigin.X - oldOrigin.X;
    difference.Y = newOrigin.Y - oldOrigin.Y;
    difference.Z = newOrigin.Z - oldOrigin.Z;

    points3D.X += difference.X;
    points3D.Y += difference.Y;
    points3D.Z += difference.Z;
    return points3D;
}

//These are to make the above functions workable with arrays of 3D points
function RotateX(points3D, degrees) // first param is an array of Point3D, func returns an array of Point3D
{
    for (i = 0; i < points3D.length; i++)
    {
        points3D[i] = RotateX(points3D[i], degrees);
    }
    return points3D;
}

function RotateY(points3D, degrees) // first param is an array of Point3D, func returns an array of Point3D
{
    for (i = 0; i < points3D.length; i++)
    {
        points3D[i] = RotateY(points3D[i], degrees);
    }
    return points3D;
}

function RotateZ(points3D, degrees) // first param is an array of Point3D, func returns an array of Point3D
{
    for (i = 0; i < points3D.length; i++)
    {
        points3D[i] = RotateZ(points3D[i], degrees);
    }
    return points3D;
}

function Translate(points3D, oldOrigin, newOrigin) // first param is an array of Point3D, func returns an array of Point3D
{
    for (i = 0; i < points3D.length; i++)
    {
        points3D[i] = Translate(points3D[i], oldOrigin, newOrigin);
    }
    return points3D;
}

function ComputeCenterPoint(points) // param is an array of 2D points, returns the center point (2D) of a polygon
{
    // Prevent Divide by Zero, make sure we have at least one point
    if (points.length > 0)
    {
        // These will store our sums
        var xSum = 0;
        var ySum = 0;

        // Loop through our points, adding to our sums
        for (i = 0; i < points.length; i++)
        {
            xSum += points[i].X;
            ySum += points[i].Y;
        }

        // These will store our averages
        var xAvg;
        var yAvg;

        // Divide each sum by total
        xAvg = xSum / points.length;
        yAvg = ySum / points.length;

        // Set the CenterPoint
        var p = new Point();
        p.X = xAvg;
        p.Y = yAvg;
        return p;
    }
    // else?
}

//////////////////////////

startMouseTracking();