/* <copyright>
This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
(c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
</copyright> */

///////////////////////////////////////////////////////////////////////
// Class GLLine
//      GL representation of a line.
//      Derived from class GLGeomObj
///////////////////////////////////////////////////////////////////////
function GLLine( world, xOffset, yOffset, width, height, slope, strokeSize, strokeColor, strokeMaterial, strokeStyle, xAdj, yAdj)
{
    ///////////////////////////////////////////////////////////////////////
    // Instance variables
    ///////////////////////////////////////////////////////////////////////
    this._width = 2.0;
    this._height = 2.0;
    this._xOffset = 0;
    this._yOffset = 0;

    // If line doesn't fit in canvas world, we had to grow the canvas by this much on either side
    this._xAdj = 0;
    this._yAdj = 0;
    
    this._slope = 0;

    this._strokeWidth = 0.25;

    this._strokeStyle = "Solid";
    this._scaleX = 1.0;
    this._scaleY = 1.0;

    if (arguments.length > 0)
    {
        this._width = width;
        this._height = height;
        this._xOffset = xOffset;
        this._yOffset = yOffset;

        this._xAdj = xAdj;
        this._yAdj = yAdj;

        this._slope = slope;
        this._strokeWidth = strokeSize;
        this._strokeColor = strokeColor;

        this._strokeStyle = strokeStyle;
        this._scaleX = (world.getViewportWidth())/(world.getViewportHeight());
    }

    this._strokeVerticesLen = 0;

    this.m_world = world;

	this._materialAmbient  = [0.2, 0.2, 0.2,  1.0];
	this._materialDiffuse  = [0.4, 0.4, 0.4,  1.0];
	this._materialSpecular = [0.4, 0.4, 0.4,  1.0];

    // initialize the inherited members
    this.inheritedFrom = GLGeomObj;
    this.inheritedFrom();

    if(strokeMaterial)
    {
        this._strokeMaterial = strokeMaterial;
    }

    ///////////////////////////////////////////////////////////////////////
    // Property Accessors
    ///////////////////////////////////////////////////////////////////////
	this.getStrokeWidth		= function()		{  return this._strokeWidth;	}
	this.setStrokeWidth		= function(w)		{  this._strokeWidth = w;		}

	this.getStrokeMaterial	= function()		{  return this._strokeMaterial;	}
	this.setStrokeMaterial	= function(m)		{  this._strokeMaterial = m;	}

    this.getStrokeColor		= function()		{  return this._strokeColor;	}
	//this.setStrokeColor	= function(c)		{  this._strokeColor = c;		}

    this.getStrokeStyle		= function()		{  return this._strokeStyle;	}
	this.setStrokeStyle		= function(s)		{  this._strokeStyle = s;		}

	this.getFillMaterial	= function()		{  return null;		}
	
	this.setStrokeMaterial  = function(m)		 {  this._strokeMaterial = m;		 }
	this.getStrokeMaterial	= function()		{  return this._strokeMaterial;		}

    this.getWidth			= function()		{  return this._width;				}
	this.setWidth			= function(w)		{  this._width = w;					}

	this.getHeight			= function()		{  return this._height;				}
	this.setHeight			= function(h)		{  this._height = h;				}

    this.getXAdj			= function()		{  return this._xAdj;			}
	this.setXAdj            = function(x)		{  this._xAdj = x;				}

    this.getYAdj			= function()		{  return this._yAdj;			}
	this.setYAdj            = function(y)		{  this._yAdj = y;				}

    this.getSlope			= function()		{  return this._slope;			}
	this.setSlope            = function(m)		{  this._slope = m;				}

    this.geomType	= function()				{  return this.GEOM_TYPE_LINE;	}

    	///////////////////////////////////////////////////////////////////////
	// Methods
	///////////////////////////////////////////////////////////////////////
	this.export = function()
	{
		var rtnStr = "type: " + this.geomType() + "\n";

		rtnStr += "xoff: "			+ this._xOffset		+ "\n";
		rtnStr += "yoff: "			+ this._yOffset		+ "\n";
		rtnStr += "width: "			+ this._width		+ "\n";
		rtnStr += "height: "		+ this._height		+ "\n";
		rtnStr += "xAdj: "		    + this._xAdj		+ "\n";
		rtnStr += "yAdj: "		    + this._yAdj		+ "\n";
		rtnStr += "strokeWidth: "	+ this._strokeWidth	+ "\n";
		rtnStr += "strokeColor: "	+ String(this._strokeColor)  + "\n";
		rtnStr += "strokeStyle: "	+ this._strokeStyle	+ "\n";
		rtnStr += "slope: "	        + String(this._slope)	+ "\n";

		rtnStr += "strokeMat: ";
		if (this._strokeMaterial)
			rtnStr += this._strokeMaterial.getName();
		else
			rtnStr += "flatMaterial";
		rtnStr += "\n";

		return rtnStr;
	}

	this.import = function( importStr )
	{
		this._xOffset			= Number( this.getPropertyFromString( "xoff: ",			importStr )  );
		this._yOffset			= Number( this.getPropertyFromString( "yoff: ",			importStr )  );
		this._width				= Number( this.getPropertyFromString( "width: ",		importStr )  );
		this._height			= Number( this.getPropertyFromString( "height: ",		importStr )  );
        this._xAdj			    = Number( this.getPropertyFromString( "xAdj: ",			importStr )  );
        this._yAdj			    = Number( this.getPropertyFromString( "yAdj: ",			importStr )  );
		this._strokeWidth		= Number( this.getPropertyFromString( "strokeWidth: ",	importStr )  );
		var slope 		        = this.getPropertyFromString( "slope: ",	importStr );
        if(isNaN(Number(slope)))
            this._slope		    = slope;
        else
            this._slope         = Number(slope);

		var strokeMaterialName	= this.getPropertyFromString( "strokeMat: ",	importStr );
		this._strokeStyle		= this.getPropertyFromString( "strokeStyle: ",	importStr );
		this._strokeColor		= eval( "[" + this.getPropertyFromString( "strokeColor: ",	importStr ) + "]" );

		var strokeMat = MaterialsLibrary.getMaterial( strokeMaterialName );
		if (!strokeMat)
		{
			console.log( "object material not found in library: " + strokeMaterialName );
			strokeMat = new FlatMaterial();
		}
		this._strokeMaterial = strokeMat;

	}

    ///////////////////////////////////////////////////////////////////////
    // Methods
    ///////////////////////////////////////////////////////////////////////
    this.buildBuffers = function()
    {
        // get the world
        var world = this.getWorld();
        if (!world)  throw( "null world in buildBuffers" );
		if (!world._useWebGL)  return;
		
		// make sure RDGE has the correct context
		g_Engine.setContext( world.getCanvas().uuid );

         // create the gl buffer
        var gl = world.getGLContext();

        this._strokeVerticesLen = 0;

        var strokeVertices = [];
        var strokeTextures = [];
        var strokeNormals = [];
        var strokeColors = [];

//        var scaleMat = Matrix.I(3);
//        scaleMat.elements[0][0] = this._scaleX;
//        scaleMat.elements[1][1] = this._scaleY;


// get the normalized device coordinates (NDC) for
		// all position and dimensions.
		var	vpw = world.getViewportWidth(),  vph = world.getViewportHeight();
		var	xNDC = 2*this._xOffset/vpw,  yNDC = 2*this._yOffset/vph,
			xFillNDC = this._width/vpw,  yFillNDC = this._height/vph,
            xAdjNDC = this._xAdj/vpw,  yAdjNDC = this._yAdj/vph,
			xStrokeNDC = this._strokeWidth/vpw,  yStrokeNDC = this._strokeWidth/vph;

		var aspect = world.getAspect();
		var zn = world.getZNear(),  zf = world.getZFar();
		var	t = zn * Math.tan(world.getFOV() * Math.PI / 360.0),
			b = -t,
			r = aspect*t,
			l = -r;

		// calculate the object coordinates from their NDC coordinates
		var z = -world.getViewDistance();

		// get the position of the origin
		var x = -z*(r-l)/(2.0*zn)*xNDC,
			y = -z*(t-b)/(2.0*zn)*yNDC;

		// get the x and y fill
		var xFill = -z*(r-l)/(2.0*zn)*xFillNDC,
			yFill = -z*(t-b)/(2.0*zn)*yFillNDC;

		// get the x & y stroke size
		var xStroke = -z*(r-l)/(2.0*zn)*xStrokeNDC,
			yStroke = -z*(t-b)/(2.0*zn)*yStrokeNDC;

        // get the x & y adjustments size
		var xAdj = -z*(r-l)/(2.0*zn)*xAdjNDC*2,
			yAdj = -z*(t-b)/(2.0*zn)*yAdjNDC*2;


        this._primArray = [];
        this._materialArray = [];
		this._materialTypeArray = [];
	    this._materialNodeArray = [];
        
        this._scaleX = (world._viewportWidth)/(world._viewportHeight);
        
        var innerX = xFill-xStroke;
        var innerY = yFill-yStroke;

//        if( (this._strokeStyle === "Dashed") || (this._strokeStyle === "Dotted") )
//        {
//            var sLen = this.createStippledStrokes(strokeVertices, this._strokeWidth, this._slope, this._strokeStyle, innerX, innerY);
//            this._strokeVerticesLen += sLen;
//        }
//        else
	      {
            if(this._slope === "vertical")
            {
                strokeVertices = [
                    -xFill+x, yFill+y,  0.0,
                    xFill+x, yFill+y,  0.0,
                    -xFill+x, -yFill+y,  0.0,

                    xFill+x, -yFill+y,  0.0,
                    -xFill+x, -yFill+y,  0.0,
                    xFill+x, yFill+y,  0.0
                ];
            }
            else if(this._slope === "horizontal")
            {
                // right now, this is the same as vertical line because,
                // our canvas is the same size as us.
                // But, we will need to use this when drawing in an existing GLWorld with other shapes
                strokeVertices = [
                    -xFill+x, yFill+y,  0.0,
                    xFill+x, yFill+y,  0.0,
                    -xFill+x, -yFill+y,  0.0,

                     xFill+x, -yFill+y,  0.0,
                    -xFill+x, -yFill+y,  0.0,
                    xFill+x, yFill+y,  0.0
               ];
            }
            else if(this._slope > 0)
            {
                // if slope is positive, draw a line from top-left to bottom-right
                strokeVertices = [
                    -xFill+x, yFill-2*yAdj+y,  0.0,
                    -xFill+2*xAdj+x, yFill+y,  0.0,
                    xFill-2*xAdj+x, -yFill+y,  0.0,

                    xFill+x, -yFill+2*yAdj+y,  0.0,
                    xFill-2*xAdj+x, -yFill+y,  0.0,
                    -xFill+2*xAdj+x, yFill+y,  0.0
                ];
            }
            else
            {
                // else slope is negative, draw a line from bottom-left to top-right
                strokeVertices = [
                    -xFill+x, -yFill+2*yAdj+y,  0.0,
                    -xFill+2*xAdj+x, -yFill+y,  0.0,
                    xFill-2*xAdj+x, yFill+y,  0.0,

                    xFill+x, yFill-2*yAdj+y,  0.0,
                    xFill-2*xAdj+x, yFill+y,  0.0,
                    -xFill+2*xAdj+x, -yFill+y,  0.0
                ];
            }
        }
        
        var z = 0;
		var indices = [];
        var nVerts = strokeVertices.length/3;
//        for(var i=0; i<nVerts; i++)
//        {
//            var vertex = Vector.create([strokeVertices[i], strokeVertices[i+1], strokeVertices[i+2]]);
//            strokeTextures.push(vertex.e(1)*0.5 + 0.5);    strokeTextures.push(vertex.e(2)*0.5 + 0.5);
//        }

		strokeTextures = [
			0, 1,
			1, 1,
			0, 0, 

			1, 1,
			0, 0,
			1, 0
		];

        // stroke normals
		var index = 0;
        for (var i=0;  i<nVerts;  i++)
        {
            // push a normal for each vertex in the stroke
            strokeNormals.push(0.0);  strokeNormals.push(0.0);  strokeNormals.push(1);
			indices.push( index );  index++;
        }

		var prim = ShapePrimitive.create(strokeVertices, strokeNormals, strokeTextures, indices, g_Engine.getContext().renderer.TRIANGLES, indices.length);

        var strokeMaterial = this.makeStrokeMaterial();

        this._primArray.push( prim );
        this._materialNodeArray.push( strokeMaterial.getMaterialNode() );

        world.updateObject(this);
    }

    this.render = function()
    {
        // get the world
        var world = this.getWorld();
        if (!world)  throw( "null world in rectangle render" );

         // get the context
		var ctx = world.get2DContext();
		if (!ctx)  return;
    
		// set up the stroke style
		var lineWidth = this._strokeWidth;
		ctx.beginPath();
		ctx.lineWidth	= lineWidth;
		ctx.strokeStyle = "#0000ff";
		if (this._strokeColor)
			ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor );

		// get the points
		var p0,  p1;
		var  w = this._width,  h = this._height;
		if(this._slope === "vertical")
        {
			p0 = [0.5*w, 0];
			p1 = [0.5*w, h];
        }
        else if(this._slope === "horizontal")
        {
			p0 = [0, 0.5*h];
			p1 = [w, 0.5*h];
        }
        else if(this._slope > 0)
        {
			p0 = [this._xAdj, this._yAdj];
			p1 = [w - this._xAdj,  h - this._yAdj];
        }
        else
        {
 			p0 = [this._xAdj, h - this._yAdj];
			p1 = [w - this._xAdj,  this._yAdj];
		}
			
		// draw the line
		ctx.moveTo( p0[0],  p0[1] );
		ctx.lineTo( p1[0],  p1[1] );
		ctx.stroke();
	}


	/*
    // type is Dotted or Dashed
    this.createStippledStrokes = function(strokeVertices, strokeSize, slope, type, innerX, innerY)
    {
        var stippleLength = strokeSize;

        if (type === "Dotted")
        {
            stippleLength = this.DOT_LENGTH;
        }
        else if(type === "Dashed")
        {
            stippleLength = this.DASH_LENGTH;
        }

        var numStrokes = 0;
        var startPos = -innerX;
        var endPos = innerX;

        var gap = this.GAP_LENGTH;
        if(slope === "horizontal")
        {
            gap *= this._scaleX;
            stippleLength *= this._scaleX;
        }
        else if(slope === "vertical")
        {
            startPos = -innerY;
            endPos = innerY;
        }
        else
        {
            if(this._scaleX < 1)
            {
                startPos = -innerY;
                endPos = innerY;
                strokeSize = (strokeSize*this._scaleX)/2;
//                strokeSize *= this._scaleX;
                stippleLength *= this._scaleX;
            }
            else
            {
                strokeSize = strokeSize/2;
                gap *= this._scaleX;
                stippleLength *= this._scaleX;
            }

        }

        while(startPos + stippleLength < endPos)
        {
            if(slope === "horizontal")
            {
                strokeVertices.push(startPos); strokeVertices.push(-strokeSize); strokeVertices.push(0);
                strokeVertices.push(startPos); strokeVertices.push(strokeSize); strokeVertices.push(0);
                strokeVertices.push(startPos+stippleLength); strokeVertices.push(-strokeSize); strokeVertices.push(0);

                strokeVertices.push(startPos); strokeVertices.push(strokeSize); strokeVertices.push(0);
                strokeVertices.push(startPos+stippleLength); strokeVertices.push(-strokeSize); strokeVertices.push(0);
                strokeVertices.push(startPos+stippleLength); strokeVertices.push(strokeSize); strokeVertices.push(0);
            }
            else if(slope === "vertical")
            {
                strokeVertices.push(-strokeSize); strokeVertices.push(startPos); strokeVertices.push(0);
                strokeVertices.push(strokeSize); strokeVertices.push(startPos); strokeVertices.push(0);
                strokeVertices.push(-strokeSize); strokeVertices.push(startPos+stippleLength); strokeVertices.push(0);

                strokeVertices.push(strokeSize); strokeVertices.push(startPos); strokeVertices.push(0);
                strokeVertices.push(-strokeSize); strokeVertices.push(startPos+stippleLength); strokeVertices.push(0);
                strokeVertices.push(strokeSize); strokeVertices.push(startPos+stippleLength); strokeVertices.push(0);
            }
            else
            {
                strokeVertices.push(startPos); strokeVertices.push(startPos*-slope-strokeSize); strokeVertices.push(0);
                strokeVertices.push(startPos); strokeVertices.push(startPos*-slope+strokeSize); strokeVertices.push(0);
                strokeVertices.push(startPos+stippleLength); strokeVertices.push((startPos+stippleLength)*-slope-strokeSize); strokeVertices.push(0);

                strokeVertices.push(startPos); strokeVertices.push(startPos*-slope+strokeSize); strokeVertices.push(0);
                strokeVertices.push(startPos+stippleLength); strokeVertices.push((startPos+stippleLength)*-slope-strokeSize); strokeVertices.push(0);
                strokeVertices.push(startPos+stippleLength); strokeVertices.push((startPos+stippleLength)*-slope+strokeSize); strokeVertices.push(0);
            }

            numStrokes += 6;

            startPos += (stippleLength+gap);
        }
//
        return numStrokes;
    }
	*/

    this.collidesWithPoint = function( x, y )
    {
        if(x < this._xOffset) return false;
        if(x > (this._xOffset + this._width)) return false;
        if(y < this._yOffset) return false;
        if(y > (this._yOffset + this._height)) return false;

        return true;
    }

 }