/*
 * Vector rendering for all browsers that support canvas.
 */

L.Browser.canvas = (function() {
	return !!document.createElement('canvas').getContext;
})();

L.Path = (L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? L.Path : L.Path.extend({
	statics: {
		//CLIP_PADDING: 0.02, // not sure if there's a need to set it to a small value
		CANVAS: true,
		SVG: false
	},
	
	options: {
		updateOnMoveEnd: true
	},
	
	_initElements: function() {
		this._map._initPathRoot();
		this._ctx = this._map._canvasCtx;
	},
	
	_updateStyle: function() {
		if (this.options.stroke) {
			this._ctx.lineWidth = this.options.weight;
			this._ctx.strokeStyle = this.options.color;
		}
		if (this.options.fill) {
			this._ctx.fillStyle = this.options.fillColor || this.options.color;
		}
	},
	
	_drawPath: function() {	
		var i, j, len, len2, point, drawMethod;
		
		this._ctx.beginPath();

		for (i = 0, len = this._parts.length; i < len; i++) {
			for (j = 0, len2 = this._parts[i].length; j < len2; j++) {
				point = this._parts[i][j];
				drawMethod = (j === 0 ? 'move' : 'line') + 'To';
				
				this._ctx[drawMethod](point.x, point.y);
			}
			// TODO refactor ugly hack
			if (this instanceof L.Polygon) {
				this._ctx.closePath();
			}
		}
	},
	
	_checkIfEmpty: function() {
		return !this._parts.length;
	},
	
	_updatePath: function() {
		if (this._checkIfEmpty()) { return; }
		
		this._drawPath();
		
		this._ctx.save();
		
		this._updateStyle();
		
		var opacity = this.options.opacity,
			fillOpacity = this.options.fillOpacity;
		
		if (this.options.fill) {
			if (fillOpacity < 1) {
				this._ctx.globalAlpha = fillOpacity;
			}
			this._ctx.fill();	
		}
		
		if (this.options.stroke) {
			if (opacity < 1) {
				this._ctx.globalAlpha = opacity;
			}
			this._ctx.stroke();
		}
		
		this._ctx.restore();
		
		/*
		 * TODO not sure if possible to implement, but a great optimization would be to do 
		 * 1 fill/stroke for all features with equal style instead of 1 for each feature 
		 */
	},

	_initEvents: function() {
		if (this.options.clickable) {
			// TODO hand cursor
			// TODO mouseover, mouseout, dblclick 
			this._map.on('click', this._onClick, this);
		}
	},
	
	_onClick: function(e) {
		if (this._containsPoint(e.layerPoint)) {
			this.fire('click', e);
		}
	},

    onRemove: function(map) {
        map.off('viewreset', this._projectLatlngs, this);
        map.off(this._updateTrigger, this._updatePath, this);
        map.fire(this._updateTrigger);
    }
});

L.Map.include((L.Path.SVG && !window.L_PREFER_CANVAS) || !L.Browser.canvas ? {} : {
	_initPathRoot: function() {
		var root = this._pathRoot,
			ctx;

		if (!root) {
			root = this._pathRoot = document.createElement("canvas");
			root.style.position = 'absolute';
			ctx = this._canvasCtx = root.getContext('2d');

			ctx.lineCap = "round";
			ctx.lineJoin = "round";

			this._panes.overlayPane.appendChild(root);

			this.on('moveend', this._updateCanvasViewport);
			this._updateCanvasViewport();
		}
	},

	_updateCanvasViewport: function() {
		this._updatePathViewport();

		var vp = this._pathViewport,
			min = vp.min,
			size = vp.max.subtract(min),
			root = this._pathRoot;

		//TODO check if it's works properly on mobile webkit
		L.DomUtil.setPosition(root, min);
		root.width = size.x;
		root.height = size.y;
		root.getContext('2d').translate(-min.x, -min.y);
	}
});