module util.animationImpl;
private import std.math;
private import util.animation;
private import util.parts;
private import util.matrix;
private import br.gamemanager;


public class Swing:Animation{
	public:
	uint degType;
	double amp;
	double alpha;
	double delay;
	public this(int span ,uint degType ,double amp ,double alpha = 0.0 ,double delay = 0.0 ,int repeat = 1){
		super(span ,repeat);
		this.degType = degType;
		this.amp = amp;
		this.alpha = alpha;
		this.delay = delay;
	}
	public void run(){
		super.run();
		if(parts !is null && parts.exists){
			parts.rotate(degType ,sin(((count) % divsp(span)) * PI * 2.0 / divsp(span) + delay *PI/180.0) * mulsp(amp) , alpha);
		}
	}

}

public class RotateTo:Animation{
	public:
	double dDeg;
	double targetDeg;
	uint degType;
	double alpha;
	public this(int span ,uint degType ,double targetDeg ,double alpha = 0.0 ,int repeat = 1){
		super(span ,repeat);
		this.degType = degType;
		this.targetDeg = targetDeg;
		this.dDeg = 0;
		this.alpha = alpha;
	}
	public void set(Parts parts){
		super.set(parts);
		if(abs(divsp(span) - count) > (1e-6)){
			dDeg =(targetDeg - *parts.pDeg(degType)) / cast(double)(divsp(span) - count + 1);
			
		}
	}
	public void run(){
		super.run();
		if(parts !is null && parts.exists){
			parts.rotate(degType ,dDeg , alpha);
		}
	}

}

public class MoveDist:Animation{
	public:
	float tdist;
	
	public this(int span ,float tdist ,int repeat = 1){
		super(span ,repeat);
		this.tdist = tdist;
	}
	public void run(){
		super.run();
		if(parts !is null && parts.exists){
			if(count <= divsp(span)){
				parts.dist += (tdist - parts.dist) / cast(float)(divsp(span) - count + 1);
			}
		}
	}
}

public class Move:Animation{
	public:
	
	double tposex, tposey ,tposez;
	double tlinkx, tlinky ,tlinkz;
/*
	double ddegx, ddegy ,ddegz;
	double ddegx2, ddegy2 ,ddegz2;
	*/
	uint degType;
	public this(int span ,uint degType ,double tdegx ,double tdegy ,double tdegz  ,int repeat = 1){
		super(span ,repeat);
		this.degType = degType;
		this.tlinkx = tdegx;this.tlinky = tdegy;this.tlinkz = tdegz;
		this.tposex = tdegx;this.tposey = tdegy;this.tposez = tdegz;
	}
	public this(int span ,uint degType ,double tdegx ,double tdegy ,double tdegz ,double tdegx2 ,double tdegy2 ,double tdegz2  ,int repeat = 1){
		super(span ,repeat);
		this.degType = degType;
		this.tlinkx = tdegx;this.tlinky = tdegy;this.tlinkz = tdegz;
		this.tposex = tdegx2;this.tposey = tdegy2;this.tposez = tdegz2;
	}
	public void set(Parts parts){
		super.set(parts);
		/*
		if(abs(span - count) > (1e-6)){
			ddegx = (tdegx - *parts.pDeg(degType)) / cast(double)(span - count);
		}
		*/
	}
	public void run(){
		super.run();
		if(parts !is null && parts.exists){
			if(count <= divsp(span)){
				if(degType & Parts.LINK){
					parts.linkX += (tlinkx - parts.linkX) / cast(float)(divsp(span) - count + 1);
					parts.linkY += (tlinky - parts.linkY) / cast(float)(divsp(span) - count + 1);
					parts.linkZ += (tlinkz - parts.linkZ) / cast(float)(divsp(span) - count + 1);
				}
				if(degType & Parts.POSE){
					parts.poseX += (tposex - parts.poseX) / cast(float)(divsp(span) - count + 1);
					parts.poseY += (tposey - parts.poseY) / cast(float)(divsp(span) - count + 1);
					parts.poseZ += (tposez - parts.poseZ) / cast(float)(divsp(span) - count + 1);
				}
			}/*else{
				if(degType & Parts.LINK){
					parts.linkX = tlinkx;
					parts.linkY = tlinky;
					parts.linkZ = tlinkz;
				}
				if(degType & Parts.POSE){
					parts.poseX = tposex;
					parts.poseY = tposey;
					parts.poseZ = tposez;
				}
			}*/
		}
	}

}

public class Rotate:Animation{
	public:
	double dDeg;
	double alpha;
	uint degType;
	public this(int span ,uint degType ,double dDeg ,double alpha = 0.0  ,int repeat = 1){
		super(span ,repeat);
		this.degType = degType;
		this.dDeg = dDeg;
		this.alpha = alpha;
	}
	public void run(){
		super.run();
		if(parts !is null && parts.exists){
			parts.rotate(degType ,mulsp(dDeg) , alpha);
		}
	}
}
public class RotateAll:Animation{
	public:
	Matrix d;
	public this(int span ,Matrix d ,bool repeat = false){
		super(span ,repeat);
		this.d = cast(Matrix)d.clone();
	}
	public void run(){
		super.run();
		if(parts !is null && parts.exists){
			parts.rotateAll(d);
		}
	}
}

public class ExtendTo:Animation{
	public:
	double dDist;
	double targetDist;
	double alpha;
	public this(int span ,double targetDist ,double alpha = 0.0  ,int repeat = 1){
		super(span ,repeat);
		this.targetDist = targetDist;
		this.dDist = 0;
		this.alpha = alpha;
	}
	public void set(Parts parts){
		super.set(parts);
		if(abs(span - count) > (1e-6)){
			dDist = (targetDist - parts.dist) / cast(double)(span - count);
		}
	}
	public void run(){
		super.run();
		if(parts !is null && parts.exists){
			parts.dist += dDist;
		}
	}

}

public class Magnification:Animation{
	public:
	double size;
	double targetSize;
//	double alpha;
	public this(int span ,double targetSize ,int repeat = 1){
		super(span ,repeat);
		this.targetSize = targetSize;
		
	}
	public void set(Parts parts){
		super.set(parts);
		
	}
	public void run(){
		super.run();
		if(parts !is null && parts.exists){
			if(count <= divsp(span)){
				parts.size = parts.size +  (targetSize - parts.size) / cast(float)(divsp(span) - count +1);
			}
		}
	}

}

public class Pulse:Animation{
	public:
	double size;
	double dSize;
//	double alpha;
	public this(int span ,double dSize ,int repeat = 1){
		super(span ,repeat);
		this.dSize = dSize;
		
	}
	public void set(Parts parts){
		super.set(parts);
		
	}
	public void run(){
		super.run();
		if(parts !is null && parts.exists){
			parts.size = parts.size +  dSize * sin(cast(double)count/cast(double)span*PI + PI/2.0);
			
		}
	}
	
	
}