package com.guru.project.papervision3D.element.base 
{
	import com.guru.project.papervision3D.element.Axis3D;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
	import org.papervision3d.core.proto.MaterialObject3D;
    import org.papervision3d.events.InteractiveScene3DEvent;
    import org.papervision3d.lights.PointLight3D;
    import org.papervision3d.objects.DisplayObject3D;
	
	/**
	 * ...
	 * @author Eddy Lee
	 */
	
    public class ModelBase extends DisplayObject3D
    {
        protected var mObjectContent:DisplayObject3D;
        protected var mObjectContainer:DisplayObject3D;
		
		protected var mMaterial_array:Array;
		protected var mPlane_array:Array;
		protected var mElement_array:Array;
		
		protected var mInnerAxis:Axis3D;
		protected var mOuterAxis:Axis3D;
		
        protected var mUpdate_bol:Boolean;
        protected var mDraggable_bol:Boolean;
        protected var mReference_obj:DisplayObject3D;
       
        protected var mSpeedX_num:Number;
        protected var mSpeedY_num:Number;
       
        protected var mPrev_pt:Point;
        protected var mCurr_pt:Point;
       
		protected var mShowAxis_bol:Boolean;
		
        protected var mFriction_num:Number = 0.9;
       
        public function ModelBase(pDraggable_bol:Boolean = false, pShowAxis_bol:Boolean = false)
        {
            mDraggable_bol = pDraggable_bol;
            mShowAxis_bol = pShowAxis_bol;
			
			mUpdate_bol = false;
            mObjectContainer = new DisplayObject3D();
            mObjectContent = new DisplayObject3D();
            mReference_obj = new DisplayObject3D();
			
			mMaterial_array = new Array();
			mPlane_array = new Array();
			mElement_array = new Array();
			
			if (mShowAxis_bol)
			{
				mInnerAxis = new Axis3D(5, 300);
				mOuterAxis = new Axis3D(20, 100);
				mObjectContainer.addChild(mOuterAxis);
				mObjectContent.addChild(mInnerAxis);
			}
			
            mCurr_pt = new Point();
            mPrev_pt = new Point();
           
            this.addChild(mObjectContainer);
            mObjectContainer.addChild(mObjectContent);
        }
		
		public function dispose():void
		{
			this.removeChild(mObjectContainer);
            mObjectContainer.removeChild(mObjectContent);
		}
		
        public function get draggable():Boolean
        {
            return mDraggable_bol;
        }
       
        public function freeze():void
        {
            mSpeedX_num = NaN;
            mSpeedY_num = NaN;
            mUpdate_bol = false;
        }
		
		public function getObjectContent():DisplayObject3D
		{
			return mObjectContent;
		}
		
        public function updateOrientation():void
        {
            if (mUpdate_bol)
            {
                if(!isNaN(mSpeedX_num) && !isNaN(mSpeedY_num))
                {
                    mObjectContainer.localRotationX += mSpeedY_num;   
                    mObjectContainer.localRotationY += mSpeedX_num;
                   
                    mSpeedX_num = mSpeedX_num * mFriction_num;
                    mSpeedY_num = mSpeedY_num * mFriction_num;
					
                    if (Math.abs(mSpeedX_num) < 0.1 && Math.abs(mSpeedY_num) < 0.1)
                    {
                        this.freeze();
                    }
                }
               
                this.updateCoordinateSystem();
            }
        }
		
		public function smoothMaterial(pSmooth_bol:Boolean):void
		{
			for (var i:Number = 0; i < mMaterial_array.length; i++)
			{
				MaterialObject3D(mMaterial_array[i]).smooth = pSmooth_bol;
			}
		}
		
		public function enablePlaneInteractive(pEnable_bol:Boolean):void
		{
			for (var i:Number = 0; i < mPlane_array.length; i++)
			{
				if(pEnable_bol)
					DisplayObject3D(mPlane_array[i]).addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, handleMouseDown);
				else
					DisplayObject3D(mPlane_array[i]).removeEventListener(InteractiveScene3DEvent.OBJECT_PRESS, handleMouseDown);
			}
		}
		
        protected function updateCoordinateSystem():void
        {
            mObjectContainer.transform.calculateMultiply(mObjectContainer.transform, mObjectContent.transform)
            mObjectContent.copyTransform(mObjectContainer);
            mObjectContainer.copyTransform(mReference_obj);
        }
       
        protected function handleMouseRelease(e:MouseEvent):void
        {
            Main.getStage().removeEventListener(MouseEvent.MOUSE_UP, handleMouseRelease);
            Main.getStage().removeEventListener(Event.ENTER_FRAME, handleMouseEnterFrame);
        }
               
        protected function handleMouseDown(e:InteractiveScene3DEvent):void
        {
            mCurr_pt.x = Main.getStage().mouseX;
            mCurr_pt.y = Main.getStage().mouseY;
			
            Main.getStage().addEventListener(MouseEvent.MOUSE_UP, handleMouseRelease);
            Main.getStage().addEventListener(Event.ENTER_FRAME, handleMouseEnterFrame);
        }
       
        protected function handleMouseEnterFrame(e:Event):void
        {
            mUpdate_bol = true;
            mPrev_pt.x = mCurr_pt.x;
            mPrev_pt.y = mCurr_pt.y;
           
            mCurr_pt.x = Main.getStage().mouseX;
            mCurr_pt.y = Main.getStage().mouseY;
           
            mSpeedX_num = (mCurr_pt.x - mPrev_pt.x) / 2;
            mSpeedY_num = (mCurr_pt.y - mPrev_pt.y) / 2;
			
			this.updateOrientation();
        }
    }
   
}