package
{
	import flash.events.*;
	import org.b2ox.pv3d.*;
	import org.libspark.thread.*;
	import org.libspark.thread.threads.utils.*;
	import org.papervision3d.objects.*;
	import org.papervision3d.view.*;
	//	import org.papervision3d.render.*;

	public class PMDViewer extends BasicView
	{
		private var rootNode:DisplayObject3D = null;
		private var cameraDistance:Number = 1000;
		private var cameraDistanceMin:Number = 100;
		private var cameraAngleX:Number = 0;
		private var cameraAngleY:Number = 0;

		public var MMDs:Vector.<MikuMikuDance> = new Vector.<MikuMikuDance>();

		public function PMDViewer():void
		{
			var thexec:IThreadExecutor;
			//thexec = new IntervalThreadExecutor(10);
			thexec = new EnterFrameThreadExecutor()
			if (!Thread.isReady) Thread.initialize(thexec);

			viewport.interactive = true;

			// 3D シーンにルートオブジェクトを作る。
			rootNode = scene.addChild(new DisplayObject3D("rootNode"));

			// カメラ設定
			initCamera();

			// ポリゴン欠けは改善されるが負荷がとんでもない
			// renderer = new QuadrantRenderEngine(QuadrantRenderEngine.ALL_FILTERS);
			startRendering();
		}

		//-------------------------------------------------
		// カメラ関連

		private function initCamera():void
		{
			camera.zoom = 800;
			camera.focus = 2;
			camera.x = 0;
			camera.y = 0;
			camera.z = -cameraDistance;
			calcCamera();

			// リスナ登録
			// stage.addEventListener にするとビルドは通るけどまともに動かない
			addEventListener(MouseEvent.MOUSE_DOWN, mouseDownEventHandler);
			addEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
			addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveEventHandler);
			addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelEventHandler);
		}

		private var pi180:Number = Math.PI / 180;
		private function calcCamera():void
		{
			rootNode.rotationY = cameraAngleY;
			camera.y = cameraDistance * Math.sin(cameraAngleX * pi180);
			camera.z = -cameraDistance * Math.cos(cameraAngleX * pi180);
		}

		private var isMouseDown:Boolean = false;
		private var _startMouseX:Number = 0, _startMouseY:Number = 0;
		private var _startCameraX:Number = 0, _startCameraY:Number = 0;
		private var _startCameraAngleX:Number = 0, _startCameraAngleY:Number = 0;
		private function mouseDownEventHandler(event:MouseEvent):void{
			isMouseDown = true;
			_startMouseX = this.mouseX;
			_startMouseY = this.mouseY;
			_startCameraX = rootNode.x;
			_startCameraY = rootNode.y;
			_startCameraAngleX = rootNode.rotationX;
			_startCameraAngleY = rootNode.rotationY;
		}

		private function mouseUpEventHandler(event:MouseEvent):void{
			isMouseDown = false;
		}

		private function mouseMoveEventHandler(event:MouseEvent):void{
			if (isMouseDown == false) return;
			if (event.shiftKey) {
				// shift+ドラッグ
				// 平行移動のコードを書く
				rootNode.x = _startCameraX - _startMouseX + this.mouseX;
				rootNode.y = _startCameraY + _startMouseY - this.mouseY;
			} else {
				cameraAngleX = _startCameraAngleX - _startMouseY + this.mouseY;
				cameraAngleY = _startCameraAngleY + _startMouseX - this.mouseX;
				if (cameraAngleX >= 180) cameraAngleX = 180;
				if (cameraAngleX <= -180) cameraAngleX = -180;
				calcCamera();
			}
		}

		private function mouseWheelEventHandler(event:MouseEvent):void {
			cameraDistance -= event.delta * 10;
			if (cameraDistance < cameraDistanceMin) cameraDistance = cameraDistanceMin;
			calcCamera();
		}

		//-------------------------------------------------

		public function addMMD(mmd:MikuMikuDance):void
		{
			rootNode.addChild(mmd);
			MMDs.push(mmd);
		}

		public function toggleMotion():void
		{
			for each (var mmd:MikuMikuDance in MMDs) {
				mmd.stop(); mmd.changeNextMotion(); mmd.play();
			}
		}

		public function play():void {
			for each (var mmd:MikuMikuDance in MMDs) {
				mmd.play();
			}
		}
		public function stop():void {
			for each (var mmd:MikuMikuDance in MMDs) {
				mmd.stop();
			}
		}
	}
}