/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.gfx.shape");

dojo.require("dojo.lang.declare");

dojo.require("dojo.gfx.common");

dojo.declare("dojo.gfx.Shape", null, {
	// summary: a Shape object, which knows how to apply
	// graphical attributes and transformations

	initializer: function(){

		// rawNode: Node: underlying node
		this.rawNode = null;

		// shape: Object: an abstract shape object
		//	(see dojo.gfx.defaultPath,
		//	dojo.gfx.defaultPolyline,
		//	dojo.gfx.defaultRect,
		//	dojo.gfx.defaultEllipse,
		//	dojo.gfx.defaultCircle,
		//	dojo.gfx.defaultLine,
		//	or dojo.gfx.defaultImage)
		this.shape = null;

		// matrix: dojo.gfx.matrix.Matrix: a transformation matrix
		this.matrix = null;

		// fillStyle: Object: a fill object
		//	(see dojo.gfx.defaultLinearGradient,
		//	dojo.gfx.defaultRadialGradient,
		//	dojo.gfx.defaultPattern,
		//	or dojo.gfx.color.Color)
		this.fillStyle = null;

		// strokeStyle: Object: a stroke object
		//	(see dojo.gfx.defaultStroke)
		this.strokeStyle = null;

		// bbox: dojo.gfx.Rectangle: a bounding box of this shape
		//	(see dojo.gfx.defaultRect)
		this.bbox = null;

		// virtual group structure

		// parent: Object: a parent or null
		//	(see dojo.gfx.Surface,
		//	dojo.gfx.shape.VirtualGroup,
		//	or dojo.gfx.Group)
		this.parent = null;

		// parentMatrix: dojo.gfx.matrix.Matrix
		//	a transformation matrix inherited from the parent
		this.parentMatrix = null;
	},

	// trivial getters
	getNode: function(){
		// summary: returns the current DOM Node or null
		return this.rawNode; // Node
	},
	getShape: function(){
		// summary: returns the current shape object or null
		//	(see dojo.gfx.defaultPath,
		//	dojo.gfx.defaultPolyline,
		//	dojo.gfx.defaultRect,
		//	dojo.gfx.defaultEllipse,
		//	dojo.gfx.defaultCircle,
		//	dojo.gfx.defaultLine,
		//	or dojo.gfx.defaultImage)
		return this.shape; // Object
	},
	getTransform: function(){
		// summary: returns the current transformation matrix or null
		return this.matrix;	// dojo.gfx.matrix.Matrix
	},
	getFill: function(){
		// summary: returns the current fill object or null
		//	(see dojo.gfx.defaultLinearGradient,
		//	dojo.gfx.defaultRadialGradient,
		//	dojo.gfx.defaultPattern,
		//	or dojo.gfx.color.Color)
		return this.fillStyle;	// Object
	},
	getStroke: function(){
		// summary: returns the current stroke object or null
		//	(see dojo.gfx.defaultStroke)
		return this.strokeStyle;	// Object
	},
	getParent: function(){
		// summary: returns the parent or null
		//	(see dojo.gfx.Surface,
		//	dojo.gfx.shape.VirtualGroup,
		//	or dojo.gfx.Group)
		return this.parent;	// Object
	},
	getBoundingBox: function(){
		// summary: returns the bounding box or null
		//	(see dojo.gfx.defaultRect)
		return this.bbox;	// dojo.gfx.Rectangle
	},
	getEventSource: function(){
		// summary: returns a Node, which is used as
		//	a source of events for this shape
		return this.rawNode;	// Node
	},

	// empty settings

	setShape: function(shape){
		// summary: sets a shape object
		//	(the default implementation simply ignores it)
		// shape: Object: a shape object
		//	(see dojo.gfx.defaultPath,
		//	dojo.gfx.defaultPolyline,
		//	dojo.gfx.defaultRect,
		//	dojo.gfx.defaultEllipse,
		//	dojo.gfx.defaultCircle,
		//	dojo.gfx.defaultLine,
		//	or dojo.gfx.defaultImage)
		return this;	// self
	},
	setFill: function(fill){
		// summary: sets a fill object
		//	(the default implementation simply ignores it)
		// fill: Object: a fill object
		//	(see dojo.gfx.defaultLinearGradient,
		//	dojo.gfx.defaultRadialGradient,
		//	dojo.gfx.defaultPattern,
		//	or dojo.gfx.color.Color)
		return this;	// self
	},
	setStroke: function(stroke){
		// summary: sets a stroke object
		//	(the default implementation simply ignores it)
		// stroke: Object: a stroke object
		//	(see dojo.gfx.defaultStroke)
		return this;	// self
	},

	// z-index

	moveToFront: function(){
		// summary: moves a shape to front of its parent's list of shapes
		//	(the default implementation does nothing)
		return this;	// self
	},
	moveToBack: function(){
		// summary: moves a shape to back of its parent's list of shapes
		//	(the default implementation does nothing)
		return this;
	},

	setTransform: function(matrix){
		// summary: sets a transformation matrix
		// matrix: dojo.gfx.matrix.Matrix: a matrix or a matrix-like object
		//	(see an argument of dojo.gfx.matrix.Matrix
		//	constructor for a list of acceptable arguments)
		this.matrix = dojo.gfx.matrix.clone(matrix ? dojo.gfx.matrix.normalize(matrix) : dojo.gfx.identity, true);
		return this._applyTransform();	// self
	},

	// apply left & right transformation

	applyRightTransform: function(matrix){
		// summary: multiplies the existing matrix with an argument on right side
		//	(this.matrix * matrix)
		// matrix: dojo.gfx.matrix.Matrix: a matrix or a matrix-like object
		//	(see an argument of dojo.gfx.matrix.Matrix
		//	constructor for a list of acceptable arguments)
		return matrix ? this.setTransform([this.matrix, matrix]) : this;	// self
	},
	applyLeftTransform: function(matrix){
		// summary: multiplies the existing matrix with an argument on left side
		//	(matrix * this.matrix)
		// matrix: dojo.gfx.matrix.Matrix: a matrix or a matrix-like object
		//	(see an argument of dojo.gfx.matrix.Matrix
		//	constructor for a list of acceptable arguments)
		return matrix ? this.setTransform([matrix, this.matrix]) : this;	// self
	},

	applyTransform: function(matrix){
		// summary: a shortcut for dojo.gfx.Shape.applyRight
		// matrix: dojo.gfx.matrix.Matrix: a matrix or a matrix-like object
		//	(see an argument of dojo.gfx.matrix.Matrix
		//	constructor for a list of acceptable arguments)
		return matrix ? this.setTransform([this.matrix, matrix]) : this;	// self
	},

	// virtual group methods

	remove: function(silently){
		// summary: removes the shape from its parent's list of shapes
		// silently: Boolean?: if true, do not redraw a picture yet
		if(this.parent){
			this.parent.remove(this, silently);
		}
		return this;	// self
	},
	_setParent: function(parent, matrix){
		// summary: sets a parent
		// parent: Object: a parent or null
		//	(see dojo.gfx.Surface,
		//	dojo.gfx.shape.VirtualGroup,
		//	or dojo.gfx.Group)
		// matrix: dojo.gfx.matrix.Matrix:
		//	a 2D matrix or a matrix-like object
		this.parent = parent;
		return this._updateParentMatrix(matrix);	// self
	},
	_updateParentMatrix: function(matrix){
		// summary: updates the parent matrix with new matrix
		// matrix: dojo.gfx.matrix.Matrix:
		//	a 2D matrix or a matrix-like object
		this.parentMatrix = matrix ? dojo.gfx.matrix.clone(matrix) : null;
		return this._applyTransform();	// self
	},
	_getRealMatrix: function(){
		// summary: returns the cumulative ("real") transformation matrix
		//	by combining the shape's matrix with its parent's matrix
		return this.parentMatrix ? new dojo.gfx.matrix.Matrix2D([this.parentMatrix, this.matrix]) : this.matrix;	// dojo.gfx.matrix.Matrix
	}
});

dojo.declare("dojo.gfx.shape.VirtualGroup", dojo.gfx.Shape, {
	// summary: a virtual group of shapes, which can be used
	//	as a foundation for renderer-specific groups, or as a way
	//	to logically group shapes (e.g, to propagate matricies)

	initializer: function() {

		// children: Array: a list of children
		this.children = [];
	},

	// group management

	add: function(shape){
		// summary: adds a shape to the list
		// shape: dojo.gfx.Shape: a shape
		var oldParent = shape.getParent();
		if(oldParent){
			oldParent.remove(shape, true);
		}
		this.children.push(shape);
		return shape._setParent(this, this._getRealMatrix());	// self
	},
	remove: function(shape, silently){
		// summary: removes a shape from the list
		// silently: Boolean?: if true, do not redraw a picture yet
		for(var i = 0; i < this.children.length; ++i){
			if(this.children[i] == shape){
				if(silently){
					// skip for now
				}else{
					shape._setParent(null, null);
				}
				this.children.splice(i, 1);
				break;
			}
		}
		return this;	// self
	},

	// apply transformation

	_applyTransform: function(){
		// summary: applies a transformation matrix to a group
		var matrix = this._getRealMatrix();
		for(var i = 0; i < this.children.length; ++i){
			this.children[i]._updateParentMatrix(matrix);
		}
		return this;	// self
	}
});

dojo.declare("dojo.gfx.shape.Rect", dojo.gfx.Shape, {
	// summary: a generic rectangle

	initializer: function(rawNode) {
		// summary: creates a rectangle
		// rawNode: Node: a DOM Node
		this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultRect, true);
		this.attach(rawNode);
	},

	getBoundingBox: function(){
		// summary: returns the bounding box (its shape in this case)
		return this.shape;	// dojo.gfx.Rectangle
	}
});

dojo.declare("dojo.gfx.shape.Ellipse", dojo.gfx.Shape, {
	// summary: a generic ellipse

	initializer: function(rawNode) {
		// summary: creates an ellipse
		// rawNode: Node: a DOM Node
		this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultEllipse, true);
		this.attach(rawNode);
	},
	getBoundingBox: function(){
		// summary: returns the bounding box
		if(!this.bbox){
			var shape = this.shape;
			this.bbox = {x: shape.cx - shape.rx, y: shape.cy - shape.ry,
				width: 2 * shape.rx, height: 2 * shape.ry};
		}
		return this.bbox;	// dojo.gfx.Rectangle
	}
});

dojo.declare("dojo.gfx.shape.Circle", dojo.gfx.Shape, {
	// summary: a generic circle
	//	(this is a helper object, which is defined for convinience)

	initializer: function(rawNode) {
		// summary: creates a circle
		// rawNode: Node: a DOM Node
		this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultCircle, true);
		this.attach(rawNode);
	},
	getBoundingBox: function(){
		// summary: returns the bounding box
		if(!this.bbox){
			var shape = this.shape;
			this.bbox = {x: shape.cx - shape.r, y: shape.cy - shape.r,
				width: 2 * shape.r, height: 2 * shape.r};
		}
		return this.bbox;	// dojo.gfx.Rectangle
	}
});

dojo.declare("dojo.gfx.shape.Line", dojo.gfx.Shape, {
	// summary: a generic line
	//	(this is a helper object, which is defined for convinience)

	initializer: function(rawNode) {
		// summary: creates a line
		// rawNode: Node: a DOM Node
		this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultLine, true);
		this.attach(rawNode);
	},
	getBoundingBox: function(){
		// summary: returns the bounding box
		if(!this.bbox){
			var shape = this.shape;
			this.bbox = {
				x:		Math.min(shape.x1, shape.x2),
				y:		Math.min(shape.y1, shape.y2),
				width:	Math.abs(shape.x2 - shape.x1),
				height:	Math.abs(shape.y2 - shape.y1)
			};
		}
		return this.bbox;	// dojo.gfx.Rectangle
	}
});

dojo.declare("dojo.gfx.shape.Polyline", dojo.gfx.Shape, {
	// summary: a generic polyline/polygon
	//	(this is a helper object, which is defined for convinience)

	initializer: function(rawNode) {
		// summary: creates a line
		// rawNode: Node: a DOM Node
		this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultPolyline, true);
		this.attach(rawNode);
	},
	getBoundingBox: function(){
		// summary: returns the bounding box
		if(!this.bbox && this.shape.points.length){
			var p = this.shape.points;
			var l = p.length;
			var t = p[0];
			var bbox = {l: t.x, t: t.y, r: t.x, b: t.y};
			for(var i = 1; i < l; ++i){
				t = p[i];
				if(bbox.l > t.x) bbox.l = t.x;
				if(bbox.r < t.x) bbox.r = t.x;
				if(bbox.t > t.y) bbox.t = t.y;
				if(bbox.b < t.y) bbox.b = t.y;
			}
			this.bbox = {
				x:		bbox.l,
				y:		bbox.t,
				width:	bbox.r - bbox.l,
				height:	bbox.b - bbox.t
			};
		}
		return this.bbox;	// dojo.gfx.Rectangle
	}
});

dojo.declare("dojo.gfx.shape.Image", dojo.gfx.Shape, {
	// summary: a generic image
	//	(this is a helper object, which is defined for convinience)

	initializer: function(rawNode) {
		// summary: creates an image
		// rawNode: Node: a DOM Node
		this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultImage, true);
		this.attach(rawNode);
	},
	getBoundingBox: function(){
		// summary: returns the bounding box
		if(!this.bbox){
			var shape = this.shape;
			this.bbox = {
				x:		0,
				y:		0,
				width:	shape.width,
				height:	shape.height
			};
		}
		return this.bbox;	// dojo.gfx.Rectangle
	}
});
