module util.beam;


private import util.parts;
private import util.vector;
private import util.basis;
private import std.math;

private import opengl;
public abstract class Beam:Parts{
	public:
	const uint MAXLOCUS;
	double maxSpeed ;
	double minSpeed ;
	double accSpeed ;
	Vector3[] locuspos;
	double[] locusaim;
	double locusR ,locusG ,locusB ,locusAlpha;
	double dDeg;
	double dDeg0;
	double speed;
	int drawDist;
	
	double taim;
	bool fixAim;
	bool rolling;
	double length;
	double rootLength;
	private:
	bool started;
	public this(uint max ,Vector3 pos ,double aim){
		MAXLOCUS = max;
		locuspos.length = MAXLOCUS;
		locusaim.length = MAXLOCUS;
		dDeg0 = dDeg = 0;
		taim = aim;
		speed = 0.0;
		started = false;
		fixAim = false;
		
		this.poseZ = aim;
		this.rposeZ = aim;
		this.linkZ = aim;
		this.rlinkZ = aim;
		
		this.pos = new Vector3();
		this.rpos = cast(Vector3)this.pos.clone();
		foreach(inout p;locuspos){
			p = cast(Vector3)rpos.clone();
		}
		foreach(inout a;locusaim){
			a = aim;
		}
		rolling = true;
	}
	
	public void move(){
		super.move();
		if(!fixAim){
			linkZ = deglimit(linkZ + dDeg);
			poseZ = linkZ;
		}
		
		for(int i = MAXLOCUS - 2;0 <= i;i --){
			locuspos[i+1] = cast(Vector3)locuspos[i].clone();
			locusaim[i+1] = locusaim[i];
		}
		
		locuspos[0] = cast(Vector3)rpos.clone();
		locusaim[0] = deglimit(rposeZ);
	}
	public void setAim(double aim ,bool moved){
		if(fixAim)return;
		dDeg= 0;

		if(moved == false){
//			dDeg = 0.6;
			speed = 0;
		}else this.taim = aim;
		
		
		if(abs(linkZ-taim)>speed){
			if(abs(linkZ-deglimit(taim+180))>speed){
				if(daimmark(linkZ ,taim) > 0){
					dDeg = speed;
					if(dDeg0 <= 0)speed =minSpeed;
					else if(maxSpeed <= speed)speed = maxSpeed;
					else speed += accSpeed;
					
				}else {
					dDeg = -speed;
					if(0 <= dDeg0)speed =minSpeed;
					else if(maxSpeed <= speed)speed = maxSpeed;
					else speed += accSpeed;
					
				}
				dDeg0 = dDeg;

			}else {
				
				if(abs(dDeg0) < (1e-6)){
					speed = minSpeed;
					dDeg = speed;
				}else 
				
				if(rolling)dDeg = dDeg0;
				else dDeg = -dDeg0;
			}
		}else{
			linkZ = taim;
			dDeg = 0;
			
			speed = 0.0;
		}
		
	}
	public void set(double rposeZ){
		this.poseZ = rposeZ;
		this.rposeZ = rposeZ;
		this.linkZ = rposeZ;
		this.taim = rposeZ;
		
		foreach(inout a;locusaim){
			a = rposeZ;
		}
		
		
		foreach(inout p;locuspos){
			p = parent.rpos; //+ new Vector3(dist * cos(linkZ) ,dist * sin(linkZ) ,0);
		} 
		
		/*
		foreach(inout a;locusaim){
			a = linkZ;
		}
		*/
	}
	
	public void draw(){
		glPushMatrix();
		super.draw();
		glPopMatrix();
		//if(started == true)throw new Exception("");
		if(started == false){
			started = true;
			for(int i = MAXLOCUS - 1;0 <= i;i --){
				locuspos[i] = cast(Vector3)rpos.clone();
				locusaim[i] = rposeZ;
			}
			
			if(started == false)throw new Exception("");
			//return;
		}
		if(started == false)throw new Exception("");
		/*
		glTranslatef(-rpos.x ,-rpos.y ,-rpos.z);
		for(int i = 0;i < (MAXLOCUS - drawDist); i+=drawDist){
			
			Vector3 pos1 = locuspos[i];
			Vector3 pos2 = locuspos[i+drawDist];
			
			double aim1 = locusaim[i];
			double aim2 = locusaim[i+drawDist];
			
			if(drawDist <= i){
				Vector3 pos0 = locuspos[i-drawDist];
				double aim0 = locusaim[i-drawDist];
//				glColor4d(locusR ,locusG ,locusB, locusAlpha * (MAXLOCUS - i) / MAXLOCUS);
				glBegin(GL_POLYGON);
				glColor4d(locusR ,locusG ,locusB, 0.0);
				glVertex3f(pos0.x ,pos0.y ,pos0.z);
				glVertex3f(pos0.x+rootLength * cos(aim0 * PI /180.0),pos0.y+rootLength * sin(aim0 * PI /180.0) ,pos0.z);
				glColor4d(locusR ,locusG ,locusB, locusAlpha * (MAXLOCUS - i) / MAXLOCUS);
				glVertex3f(pos1.x+rootLength * cos(aim1 * PI /180.0),pos1.y+rootLength * sin(aim1 * PI /180.0) ,pos1.z);
				glColor4d(locusR ,locusG ,locusB, 0.0);
				glVertex3f(pos1.x ,pos1.y ,pos1.z);
				glEnd();
				glBegin(GL_POLYGON);
				glColor4d(locusR ,locusG ,locusB , 0.0 );
				glVertex3f(pos0.x+rootLength * cos(aim0 * PI /180.0),pos0.y+rootLength * sin(aim0 * PI /180.0) ,pos0.z);
				glVertex3f(pos0.x+length * cos(aim0 * PI /180.0),pos0.y+length * sin(aim0 * PI /180.0) ,pos0.z);
				glColor4d(locusR ,locusG ,locusB, locusAlpha * (MAXLOCUS - i) / MAXLOCUS);
				glVertex3f(pos1.x+length * cos(aim1 * PI /180.0),pos1.y+length * sin(aim1 * PI /180.0) ,pos1.z);
				glVertex3f(pos1.x+rootLength * cos(aim1 * PI /180.0),pos1.y+rootLength * sin(aim1 * PI /180.0) ,pos1.z);
				glEnd();
			}
			
			glBegin(GL_POLYGON);
			glColor4d(locusR ,locusG ,locusB, 0.0);
			glVertex3f(pos2.x ,pos2.y ,pos2.z);
			glVertex3f(pos2.x+rootLength * cos(aim2 * PI /180.0),pos2.y+rootLength * sin(aim2 * PI /180.0) ,pos2.z);
			glColor4d(locusR ,locusG ,locusB, locusAlpha * (MAXLOCUS - i) / MAXLOCUS);
			glVertex3f(pos1.x+rootLength * cos(aim1 * PI /180.0),pos1.y+rootLength * sin(aim1 * PI /180.0) ,pos1.z);
			glColor4d(locusR ,locusG ,locusB, 0.0);
			glVertex3f(pos1.x ,pos1.y ,pos1.z);
			glEnd();
			
			glBegin(GL_POLYGON);
			glColor4d(locusR ,locusG ,locusB , 0.0 );
			glVertex3f(pos2.x+rootLength * cos(aim2 * PI /180.0),pos2.y+rootLength * sin(aim2 * PI /180.0) ,pos2.z);
			glVertex3f(pos2.x+length * cos(aim2 * PI /180.0),pos2.y+length * sin(aim2 * PI /180.0) ,pos2.z);
			glColor4d(locusR ,locusG ,locusB, locusAlpha * (MAXLOCUS - i) / MAXLOCUS);
			glVertex3f(pos1.x+length * cos(aim1 * PI /180.0),pos1.y+length * sin(aim1 * PI /180.0) ,pos1.z);
			glVertex3f(pos1.x+rootLength * cos(aim1 * PI /180.0),pos1.y+rootLength * sin(aim1 * PI /180.0) ,pos1.z);
			glEnd();
			
		*/
		
		glEnable(GL_BLEND);
		
		
//		glPushMatrix();
//		glTranslatef(locuspos[0].x - rpos.x ,locuspos[0].y - rpos.y ,locuspos[0].z - rpos.z);
		/*
		glBegin(GL_POLYGON);
		glColor4d(locusR ,locusG ,locusB, 0.0);
		glVertex3f(0.0 ,0.0 ,0.0);
		glColor4d(locusR ,locusG ,locusB , locusAlpha * drawDist / MAXLOCUS );
		glVertex3f(rootLength * cos(linkZ * PI /180.0),rootLength * sin(linkZ * PI /180.0) ,0.0);
		glColor4d(locusR ,locusG ,locusB, 0.0);
		glVertex3f(rootLength * cos(locusaim[0] * PI /180.0),rootLength * sin(locusaim[0] * PI /180.0) ,0.0);
		glColor4d(locusR ,locusG ,locusB, 0.0);
		glVertex3f(0.0 ,0.0 ,0.0);
		glEnd();
		glBegin(GL_POLYGON);
		glColor4d(locusR ,locusG ,locusB , locusAlpha * drawDist / MAXLOCUS );
		glVertex3f(rootLength * cos(linkZ * PI /180.0),rootLength * sin(linkZ * PI /180.0) ,0.0);
		glVertex3f(length * cos(linkZ * PI /180.0),length * sin(linkZ * PI /180.0) ,0.0);
		glColor4d(locusR ,locusG ,locusB, 0.0);
		glVertex3f(length * cos(locusaim[0] * PI /180.0),length * sin(locusaim[0] * PI /180.0) ,0.0);
		glVertex3f(rootLength * cos(locusaim[0] * PI /180.0),rootLength * sin(locusaim[0] * PI /180.0) ,0.0);
		glEnd();
		
		*/
//		glPopMatrix();
		
		for(int i = 0;i < (MAXLOCUS - drawDist); i+=drawDist){
			
			glPushMatrix();
			glBegin(GL_POLYGON);
			glColor4d(locusR ,locusG ,locusB, 0.0);
			glVertex3f(rpos.x ,rpos.y ,rpos.z);
			glColor4d(locusR ,locusG ,locusB , locusAlpha * drawDist / MAXLOCUS );
			glVertex3f(rpos.x+rootLength * cos(rposeZ*PI/180) ,rpos.y+rootLength * sin(rposeZ*PI/180) ,rpos.z);
			
			glColor4d(locusR ,locusG ,locusB, 0.0);
			glVertex3f(locuspos[i+drawDist].x +rootLength * cos(locusaim[i+drawDist] * PI /180.0),locuspos[i+drawDist].y+rootLength * sin(locusaim[i+drawDist] * PI /180.0) ,locuspos[i+drawDist].z);
			glVertex3f(locuspos[i+drawDist].x ,locuspos[i+drawDist].y ,locuspos[i+drawDist].z);
			glEnd();
			glBegin(GL_POLYGON);
			
			glColor4d(locusR ,locusG ,locusB , locusAlpha * drawDist / MAXLOCUS );
			glVertex3f(rpos.x+rootLength * cos(rposeZ * PI /180.0),rpos.y+rootLength * sin(rposeZ * PI /180.0) ,rpos.z);
			glVertex3f(rpos.x+length * cos(rposeZ*PI/180) ,rpos.y+length * sin(rposeZ*PI/180) ,rpos.z);
			for(int j=0;j<i+drawDist;j++){
				glColor4d(locusR ,locusG ,locusB, locusAlpha * drawDist / MAXLOCUS * (i+drawDist -j) /(i+drawDist));
				glVertex3f(locuspos[j].x +length * cos(locusaim[j] * PI /180.0),locuspos[j].y +length * sin(locusaim[j] * PI /180.0) ,locuspos[j].z);
			}
			glColor4d(locusR ,locusG ,locusB, 0.0);
			glVertex3f(locuspos[i+drawDist].x +length * cos(locusaim[i+drawDist] * PI /180.0),locuspos[i+drawDist].y +length * sin(locusaim[i+drawDist] * PI /180.0) ,locuspos[i+drawDist].z );
			glVertex3f(locuspos[i+drawDist].x +rootLength * cos(locusaim[i+drawDist] * PI /180.0),locuspos[i+drawDist].y +rootLength * sin(locusaim[i+drawDist] * PI /180.0) ,locuspos[i+drawDist].z );
			
			glEnd();
			glPopMatrix();
			
		
		
		}
		
		glDisable(GL_BLEND);
	}
	public void reportCollision(int kind ,Parts p){}
		
}

