import o0 from "./o0.js"

module.exports = {
	Filter: class {
		constructor() {

			this.stableAcceleration = null;
			this.maxrecordCount = 999999;

			this.frame = [];
			this.frameHit = []; //打击后的n帧
			for (var i = 0; i < 200; ++i) {
				var o = new Object();
				o.time = new Date().getTime();
				o.timeGap = 20;
				o.acc = new o0.Vector2(0, 0);
				o.accFixed = 0;
				o.accSlope = 0;
				o.pos = new o0.Vector2(0, 0);
				o.predict = new o0.Vector2(0, 0);
				o.shake = 0;
				o.shakeFixed = 1;
				o.shakeSlope = 0;
				o.hit = 0;
				this.frame.push(o);
				//this.frameHit.push(o);
			}
			//this.frame = 0;

			this.force = new o0.Vector2(0, 0);
			this.forceChanged = 0;
			this.momentum = 999999;
			this.momentunTime = 0;
			this.momentunSeek = 0.1;
			this.momentunPunch = false;
			this.punchCount = 0;
			this.leftRight = false;

			this.forceRecord = [];
			for (var i = 0; i < 1; ++i) {
				this.forceRecord.push(new o0.Vector2(0, 0));
			} /** */
			this.angle = 0;

			this.quitHitCount = 0;
		}
		Update(vector3, timeGap, callback) {
			// console.log(vector3,timeGap,callback);
			if (this.stableAcceleration == null) {
				this.stableAcceleration = vector3;
				this.recordCount = 1;
			} else {
				this.recordCount += 1;
				if (this.recordCount > this.maxrecordCount) {
					this.recordCount = this.maxrecordCount;
				}
				let recordCount = this.recordCount;
				this.stableAcceleration = this.stableAcceleration.multiply((recordCount - 1) / recordCount).plus(vector3.multiply(
					1 / recordCount));
			}

			//++this.frame;

			var newForce = vector3.minus(this.stableAcceleration);

			var newFrame = new Object();
			newFrame.time = new Date().getTime();
			newFrame.timeGap = timeGap;
			newFrame.acc = new o0.Vector2(newForce.x, newForce.z);
			let lastFrame = this.frame[this.frame.length - 1];
			let last2Frame = this.frame[this.frame.length - 2];
			let last3Frame = this.frame[this.frame.length - 3];
			let last4Frame = this.frame[this.frame.length - 4];
			let last5Frame = this.frame[this.frame.length - 5];
			//////////////////////////////////////////////////////////////////////
			newFrame.accFixed = newFrame.acc.length * 100;

			if (newFrame.accFixed < lastFrame.accFixed * 0.85) {
				newFrame.accFixed = lastFrame.accFixed * 0.85;
			}
			lastFrame.accFixed = Math.max(lastFrame.accFixed, Math.min(newFrame.accFixed, last2Frame.accFixed), Math.min(
				newFrame.accFixed, last3Frame.accFixed));
			///////////////////////////////////////////////////////////////////////
			//newFrame.pos = lastFrame.pos.plus(lastFrame.acc.plus(newFrame.acc).multiply(timeGap/60)).multiply(Math.max(1-timeGap/200,0));
			newFrame.pos = lastFrame.pos.plus(newFrame.acc.multiply(timeGap / 30)).multiply(Math.max(1 - timeGap / 1000, 0));
			////////////////////////////////////////////
			var accSlpoe1 = (newFrame.accFixed - lastFrame.accFixed);
			var accSlpoe2 = (newFrame.accFixed - last2Frame.accFixed);
			var accSlpoe3 = (newFrame.accFixed - last3Frame.accFixed);
			//newFrame.accSlope = accSlpoe1;
			//newFrame.accSlope = Math.min(accSlpoe1,accSlpoe2);
			//newFrame.accSlope = Math.min(accSlpoe1,accSlpoe2,accSlpoe3);
			newFrame.accSlope = Math.max(newFrame.accFixed - lastFrame.accFixed, 0);

			/*
			if(newFrame.accSlope > 8){
				newFrame.accSlope = 1; 
			}else if(newFrame.accSlope <= 8){
				newFrame.accSlope = 0;
			}/** */
			/////////////////////////////////////////////////

			var lastI = this.frame.length - 1;
			var t2 = this.frame[lastI - 1].timeGap;
			var t3 = this.frame[lastI].timeGap + t2;
			var t4 = newFrame.timeGap + t3;

			/*newFrame.predict = new o0.Vector2(
				new o0.QuadraticEquation(0,this.frame[lastI-2].acc.x,t2,this.frame[lastI-1].acc.x,t3,this.frame[lastI].acc.x).y(t4),
				new o0.QuadraticEquation(0,this.frame[lastI-2].acc.y,t2,this.frame[lastI-1].acc.y,t3,this.frame[lastI].acc.y).y(t4));/** */
			/*
			newFrame.predict = new o0.Vector2(
				new o0.QuadraticEquation(0,this.frame[lastI-2].pos.x,t2,this.frame[lastI-1].pos.x,t3,this.frame[lastI].pos.x).y(t4),
				new o0.QuadraticEquation(0,this.frame[lastI-2].pos.y,t2,this.frame[lastI-1].pos.y,t3,this.frame[lastI].pos.y).y(t4));/** */

			newFrame.predict = new o0.Vector2(
				new o0.QuadraticEquation(0, this.frame[lastI - 2].pos.x, t2, this.frame[lastI - 1].pos.x, t3, this.frame[lastI]
					.pos.x).y(t4),
				new o0.QuadraticEquation(0, this.frame[lastI - 2].pos.y, t2, this.frame[lastI - 1].pos.y, t3, this.frame[lastI]
					.pos.y).y(t4)); /** */
			//console.log(newFrame.pos);
			//////////////////////////////////////////
			//newFrame.shake = o0.distance2(newFrame.predict,newFrame.pos) * 500;
			//console.log(newFrame.pos.minus(lastFrame.pos).mod.angle(newFrame.predict.minus(lastFrame.pos).mod));

			//newFrame.shake = o0.distance2(newFrame.predict,newFrame.acc) * 100;
			newFrame.shake = o0.distance2(newFrame.predict, newFrame.pos) * 100;


			//newFrame.shake = o0.distance2(newFrame.predict,lastFrame.pos) * newFrame.acc.length / timeGap * 2000;

			if (isNaN(newFrame.shake)) {
				newFrame.shake = 0.0;
			} /** */
			//newFrame.shake = Math.pow(o0.distance2(newFrame.predict,newFrame.pos) * newFrame.acc.length / timeGap,0.5) * 500;
			/////////////////////////////下面的代码有优化空间
			//newFrame.shakeFixed = lastFrame.shakeFixed * 0.9;
			//newFrame.shakeFixed = lastFrame.shakeFixed*(1.0+newFrame.shake)*0.9;
			//newFrame.shakeFixed = Math.pow(lastFrame.shakeFixed*(1.0+newFrame.shake),0.5)+1;
			//console.log(newFrame.shakeFixed+1);
			//newFrame.shakeFixed = newFrame.shake;

			newFrame.shakeFixed = lastFrame.shakeFixed * 0.85;
			if (newFrame.shake > newFrame.shakeFixed) {
				newFrame.shakeFixed = newFrame.shake;
			} /* */
			lastFrame.shakeFixed = Math.max(lastFrame.shakeFixed, Math.min(newFrame.shakeFixed, last2Frame.shakeFixed), Math.min(
				newFrame.shakeFixed, last3Frame.shakeFixed));
			////////////////////////////////////////////////////////////////
			/*
			var shakeSlpoe1 = (newFrame.shakeFixed-lastFrame.shakeFixed);
			var shakeSlpoe2 = (newFrame.shakeFixed-last2Frame.shakeFixed);
			var shakeSlpoe3 = (newFrame.shakeFixed-last3Frame.shakeFixed);
			//newFrame.accSlope = accSlpoe1;
			//newFrame.accSlope = Math.min(accSlpoe1,accSlpoe2);
			newFrame.shakeSlope = Math.min(shakeSlpoe1,shakeSlpoe2,shakeSlpoe3);
			newFrame.shakeSlope = Math.max(newFrame.shakeSlope,0);/** */
			newFrame.shakeSlope = Math.max(newFrame.shakeFixed - lastFrame.shakeFixed, 0);

			/*
			if(newFrame.shakeSlope > 40){
				newFrame.shakeSlope = 1;
			}else{
				newFrame.shakeSlope = 0;
			}/** */
			//////////////////////////////////////////////
			/*
			var slopeChange = newFrame.shakeFixed - lastFrame.shakeFixed;
			if(slopeChange < 0){
				newFrame.slope = (lastFrame.slope + (newFrame.shakeFixed - lastFrame.shakeFixed) / timeGap * 100) * 0.8;
			}else{
				newFrame.slope = (lastFrame.slope + (newFrame.shakeFixed - lastFrame.shakeFixed) / timeGap * 20) * 0.8;
			}
			if(newFrame.slope<0){
				newFrame.slope = 0;
			}/** */
			/////////////////////////////下面的代码有很大优化空间
			if (lastFrame.hit == 0 &&
				last2Frame.hit == 0 &&
				last3Frame.hit == 0 &&
				last4Frame.hit == 0 &&
				last5Frame.hit == 0 &&
				(newFrame.accSlope >= 15 || lastFrame.accSlope >= 20) &&
				(newFrame.shakeSlope >= 20 || lastFrame.shakeSlope >= 40)) {
				newFrame.hit = newFrame.shake;
				this.frameHit = [];
			} else {
				newFrame.hit = 0;
			}


			/*
			if(lastFrame.hit == 0 
				&& this.frame[this.frame.length-2].hit == 0
				&& this.frame[this.frame.length-3].hit == 0
				&& newFrame.shakeFixed > 150
				&& newFrame.shakeFixed > lastFrame.shakeFixed * 2){
				newFrame.hit = newFrame.shakeFixed;
			}else{
				newFrame.hit = 0;
			}/** */
			/////////////力量大小
			// if(lastFrame.hit!=0){
			// 	lastFrame.hit = Math.max(lastFrame.hit,newFrame.shakeFixed)
			// }else if(this.frame[this.frame.length-2].hit!=0){
			// 	this.frame[this.frame.length-2].hit = Math.max(this.frame[this.frame.length-2].hit,newFrame.shakeFixed)
			// 	// console.log(this.frame[this.frame.length-2].hit);
			// 	// this.quitHitCount ++;
			// 	// console.log(this.quitHitCount);

			// 	if(callback){
			// 		let temp = {
			// 			type:'hit',
			// 			hit:this.frame[this.frame.length-2].hit,
			// 			hitCount : this.quitHitCount
			// 		}
			// 		callback(temp);
			// 	}
			// }
			if (lastFrame.hit != 0) {
				lastFrame.hit = lastFrame.hit + newFrame.shake;
			} else if (last2Frame.hit != 0) {
				last2Frame.hit = last2Frame.hit + newFrame.shake;
			} else if (last3Frame.hit != 0) {
				last3Frame.hit = last3Frame.hit + newFrame.shake;
			} else if (last4Frame.hit != 0) {
				last4Frame.hit = last4Frame.hit + newFrame.shake;
			} else if (last5Frame.hit != 0) {
				last5Frame.hit = last5Frame.hit + newFrame.shake;
				console.log(last5Frame.hit/5);
				this.quitHitCount++;
				if (callback) {
					let temp = {
						type: 'hit',
						hit: last5Frame.hit/5,
						hitCount: this.quitHitCount
					}
					callback(temp);
				}
			}
			/** */
			//newFrame.shake = o0.distance2(newFrame.predict,newFrame.pos) * o0.distance2(lastFrame.pos,newFrame.pos);
			//////////////////////
			this.frame.shift();
			this.frame.push(newFrame);
			if (this.frameHit.length <= 17) {
				var o = new Object();
				o.time = newFrame.time;
				o.timeGap = newFrame.timeGap;
				o.acc = newFrame.acc;

				let frameHitLength = this.frameHit.length + 1;
				let lastFrameHit = this.frameHit[this.frameHit.length - 1];
				if (frameHitLength == 1) {
					o.allShakeLength = newFrame.shakeFixed;
				} else {
					o.allShakeLength = lastFrameHit.allShakeLength + newFrame.shakeFixed;
				}

				o.accFixed = o.acc.multiply(Math.pow(Math.max(0, 1 - newFrame.shakeFixed * frameHitLength / o.allShakeLength), 5) *
					20); //数字越大越忽略历史数据

				if (frameHitLength == 1) {
					o.pos = o.accFixed.multiply(o.timeGap / 60);
				} else {
					o.pos = lastFrameHit.pos.plus(lastFrameHit.accFixed.plus(o.accFixed).multiply(o.timeGap / 60));
				}
				this.frameHit.push(o);
			}




			var vectorChanged = newForce.minus(this.force);
			var forceLength = this.force.length;
			var ForceChanged = newForce.length - forceLength;
			this.force = newForce;

			var currentLeftRight;
			if (Math.abs(newForce.x + newForce.z) > Math.abs(newForce.x - newForce.z)) {
				currentLeftRight = Math.abs(newForce.x + newForce.z);
			} else {
				currentLeftRight = -Math.abs(newForce.x - newForce.z);
			}
			this.forceRecord.shift();
			this.forceRecord.push(newForce);

			if (this.forceChanged > 0 && ForceChanged < 0) { // && forceLength > 0.1
				//&& this.momentum * Math.pow(0.9,(new Date().getTime()-this.momentunTime)/1) < forceLength){
				/*console.log(forceLength.toFixed(2));
				if( forceLength > 0.1 && forceLength >= this.momentum * 1.5){
					console.log(this.frame+" "+forceLength);
				}/** */
				if (forceLength > 0.1 && this.momentum != 999999) {
					if (!this.momentunPunch) { //等待击打
						if (this.momentunSeek > this.momentum) {
							this.momentunSeek = this.momentum;
						} else {
							if (this.momentunSeek < this.momentum * 0.8 - 0.1) {
								this.momentunPunch = !this.momentunPunch;
								this.punchCount++;
								//this.leftRight = (newForce.x+this.force.x) < 0;

								/*
								var largestForce = new o0.Vector3(0,0,0)
								for(var i = 0;i<this.forceRecord.length;++i){
									var element = this.forceRecord[i];
									if(largestForce.length < element.length){
										largestForce = element;
									}
								}
								if(Math.abs(largestForce.x + largestForce.z) > Math.abs(largestForce.x - largestForce.z)){
									currentLeftRight = Math.abs(largestForce.x + largestForce.z);
								}else{
									currentLeftRight = -Math.abs(largestForce.x - largestForce.z);
								}/** */
								this.leftRight = currentLeftRight < 0 ? "Right" : "Left";
								this.angle = new o0.Vector2(newForce.x, newForce.z).mod.angle(new o0.Vector2(0, 1));
								if (this.angle > 90) {
									this.angle = 180 - this.angle;
								}
								if (currentLeftRight > 0) {
									this.angle = -this.angle;
								} /** */
								//this.leftRight = (largestChange.x > 0 && largestChange.z > 0) || (largestChange.x < 0 && largestChange.z < 0);
								/* */
								//console.log(this.momentum);
							}
						}
					} else { //打完了
						if (this.momentunSeek < this.momentum) {
							this.momentunSeek = this.momentum;
						} else if (this.momentunSeek > this.momentum * 1.2 + 0.1) {
							this.momentunPunch = !this.momentunPunch;
						}
					}
				}

				this.momentum = forceLength;
				this.momentunTime = new Date().getTime();
			}

			this.forceChanged = ForceChanged;



			//console.log(vector3.x);
			return [new o0.Vector3(newForce), currentLeftRight, this.momentum];
		}
		test() {
			return "123123131";
		}
	}
};
