package {
	import com.netgrind.core.Utils;
	import com.netgrind.core.Mouse;
	import adobe.utils.CustomActions;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import nape.geom.GeomPoly;
	import nape.geom.GeomPolyIterator;
	import nape.geom.GeomPolyList;
	import nape.geom.GeomVertexIterator;
	import nape.geom.Vec2;
	import nape.phys.Body;
	import nape.shape.Polygon;
	
	/**
	 * ...
	 * @author netgrind
	 */
	public class Poly extends Sprite {
		public static var all:Vector.<Poly> = new Vector.<Poly>();
		
		public var poly:Polygon;
		public var handles:Vector.<Handle>
		public var color:uint = 0x88ffff;
		public var menu:Array = [];
		public var body:Body;
		private var _type:int = 1;
		
		public static const TYPE_ROAD:int = 0;
		public static const TYPE_WALL:int = 1;
		public static const TYPE_GRASS:int = 2;
		
		
		public function Poly(body:Body, verts:Vector.<Vec2>, type:int = 1) {
			all.push(this);
			this.body = body;
			alpha = .5;
			poly = new Polygon(verts);
			body.shapes.add(poly);
			handles = new Vector.<Handle>();
			for (var i:int = 0; i < verts.length; i++) {
				handles.push(new Handle(verts[i].x, verts[i].y, onMoveHandle));
				handles[i].addMenuItem("remove vert", removeHandle,handles[i]);
			}
			addEventListener(MouseEvent.RIGHT_MOUSE_DOWN, onRightDown);
			addEventListener(MouseEvent.MOUSE_DOWN, onDown);
			
			menu.push(["add vert",addVert]);
			menu.push(["delete poly",deletePoly]);
			menu.push(["set road",setType, [TYPE_ROAD]]);
			menu.push(["set wall",setType, [TYPE_WALL]]);
			menu.push(["set grass", setType, [TYPE_GRASS]]);
			
			this.type = type;
			draw();
		}
		
		public function addVert():void {
			var v:Vec2 = new Vec2(mouseX, mouseY);
			poly.localVerts.add(v);
			
			var h:Handle = new Handle(v.x, v.y, onMoveHandle);
			handles.push(h);
			h.addMenuItem("remove vert", removeHandle, h);
			draw();
		}
		
		public function saveString():String {
			var s:String = "";
			for (var i:int = 0; i < handles.length; i++) {
				s += handles[i].x + "|" + handles[i].y + "|";
			}
			s += "|";
			s += type+"";
			return s;
		}
		
		public static function createFromString(s:String, body:Body):Poly {
			var a:Array = s.split("||");
			var p:Array = a[0].split("|");
			var v:Vector.<Vec2> = new Vector.<Vec2>();
			for (var i:int = 0; i < p.length; i += 2) {
				v.push(new Vec2(p[i], p[i + 1]));
			}
			return new Poly(body,v, a[1]);
		}
		
		private function onDown(e:MouseEvent):void {
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
			stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
		}
		
		private function onUp(e:MouseEvent):void {
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
		}
		
		private function onMove(e:MouseEvent):void {
			for (var i:int = 0; i < handles.length; i++) {
				handles[i].x += Mouse.deltaX;
				handles[i].y += Mouse.deltaY;
			}
			draw();
		}
		
		private function setType(i:int):void {
			type = i;
		}
		
		public function deletePoly():void {
			kill();
		}
		
		private function onRightDown(e:MouseEvent):void {
			e.stopPropagation();
			ContextMenu.target(e.stageX, e.stageY, menu);
		}
		
		private function removeHandle(h:Handle):void {
			var i:int = handles.indexOf(h);
			if (i != -1) {
				handles.splice(i, 1);
				h.kill();
				h =  null;
				draw();
			}			
		}
		
		public function onMoveHandle():void {
			draw();
		}
		
		public function draw():void {
			this.graphics.clear();
			if(Main.debug){
				this.graphics.beginFill(color, alpha);
				this.graphics.lineStyle(4,color, alpha * 1.2);
				for (var i:int = 0; i < handles.length; i++) {
					poly.localVerts.at(i).x = handles[i].x;
					poly.localVerts.at(i).y = handles[i].y;
					if (i == 0) graphics.moveTo(handles[i].x, handles[i].y);
					else graphics.lineTo(handles[i].x, handles[i].y);
				}
				this.graphics.endFill();
			}
		}
		
		public function subdivide():void {
			var g:GeomPoly = new GeomPoly(poly.localVerts);
			var a:GeomPolyList = g.convexDecomposition(false);
			var p:GeomVertexIterator;
			if (a.length > 1) {
				for (var i:int = 0; i < a.length; i++) {
					p = a.at(i).forwardIterator();
					var v:Vector.<Vec2> = new Vector.<Vec2>();
					while (p.hasNext()) {
						v.push(p.next());
					}
					parent.addChild(new Poly(body, v, type));;
				}
				kill();
			}
			g.dispose();
			g = null;
			a = null;
		}
		
		public function kill():void {
			var i:int = all.indexOf(this);
			if (i != -1) all.splice(i, 1);
			Utils.removeChild(this);
			body.shapes.remove(poly);
			poly = null;
		}
		
		public function get type():int {return _type;}		
		public function set type(value:int):void {
			_type = value;
			if (_type == 0) color = 0xff3333;
			else if (_type == 1) color = 0x3333ff;
			else if (_type == 2) color = 0x33ff33;
			draw();
		}
	}
}