import o0 from "./o0.js"

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

			this.stableAcc = new o0.Vector2(0, 0);
			this.stableGyr = new o0.Vector2(0, 0);
			this.stableCount = 0;
			this.stableCountMax = 3000;

			this.frameCapacity = 6;
			this.frame = [];
			this.frameLength = 5;
			this.frameOffset = 0;

			this.frameHitCapacity = 11;
			this.frameHit = [];//打击后的n帧

			for (var i = 0; i < this.frameCapacity; ++i) {
				var o = new Object();
				o.acc = new o0.Vector2(0, 0);
				o.gyr = new o0.Vector2(0, 0);

				o.timeGap = 20;
				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 = 0;
				o.shakeSlope = 0;

				o.hit = 0;
				this.frame.push(o);
			}

			this.quitHitCount = 0;
		}
		//这个函数不建议外部调用
		GetDirection() {
			var direction = new o0.Vector2(0, 0);
			var directionDistance = 0.0;
			for (var fi = 0; fi < this.frameHit.length - 1; ++fi) {
				for (var li = fi + 1; li < this.frameHit.length; ++li) {
					var newDirection = this.frameHit[li].gyr.minus(this.frameHit[fi].gyr);
					var newDirectionDistance = newDirection.length;
					if (directionDistance < newDirectionDistance) {
						directionDistance = newDirectionDistance;
						direction = newDirection.multiply(this.frameHit[this.frameHit.length - 1].time - this.frameHit[0].time);
					}
					else {
						//cout << "false" << endl;
					}
				}
			}
			return direction;
		}
		// 输入俯视的平面坐标系下的xy轴坐标 的 加速计向量/陀螺仪向量。
		// timeGap 代表当前帧读取传感器与上一帧读取传感器 之间的时间差
		Update(accX, accY, gyrX, gyrY, timeGap) {
			var rawAcc = new o0.Vector2(accX, accY);
			var rawGyr = new o0.Vector2(gyrX, gyrY);

			let lastFrame = this.frame[(this.frameOffset + this.frameLength - 1) % this.frameCapacity];
			let last2Frame = this.frame[(this.frameOffset + this.frameLength - 2) % this.frameCapacity];
			let last3Frame = this.frame[(this.frameOffset + this.frameLength - 3) % this.frameCapacity];
			let last4Frame = this.frame[(this.frameOffset + this.frameLength - 4) % this.frameCapacity];
			let last5Frame = this.frame[(this.frameOffset + this.frameLength - 5) % this.frameCapacity];
			var newFrame = this.frame[(this.frameOffset + this.frameLength) % this.frameCapacity];

			newFrame.timeGap = timeGap;

			newFrame.acc = rawAcc.minus(this.stableAcc);
			newFrame.gyr = rawGyr.minus(this.stableGyr);

			if (this.stableCount < this.stableCountMax) {
				this.stableCount += 1;
			}
			this.stableAcc = this.stableAcc.multiply((this.stableCount - 1.0) / this.stableCount).plus(rawAcc.multiply(1 / this.stableCount));
			this.stableGyr = this.stableGyr.multiply((this.stableCount - 1.0) / this.stableCount).plus(rawGyr.multiply(1 / this.stableCount));
			//////////////////////////////////////////////////////////////////////////////////
			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));
			////////////////////////////////////////////
			newFrame.accSlope = Math.max(newFrame.accFixed - lastFrame.accFixed, 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].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.shake = o0.distance2(newFrame.predict, newFrame.pos) * 100;


			if (isNaN(newFrame.shake)) {
				newFrame.shake = 0.0;
			}

			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));
			////////////////////////////////////////////////////////////////
			newFrame.shakeSlope = Math.max(newFrame.shakeFixed - lastFrame.shakeFixed, 0);
			///////////////////////////////////////////////////////////////

			var direction = undefined;

			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 = 1;
				if (this.frameHit.length < this.frameHitCapacity && this.frameHit.length != 0) {//判断到第二次hit，但还未输出第一次hit的方向，强制输出方向
					direction = this.GetDirection();
				}/**/
				this.frameHit = [];

				/*
				var o3 = new Object();
				o3.time = 0;
				o3.gyr = lastFrame3.gyr;
				this.frameHit.push(o3);/* */

				var o2 = new Object();
				o2.time = last2Frame.timeGap;
				o2.gyr = last2Frame.gyr;
				this.frameHit.push(o2);

				var o = new Object();
				o.time = last2Frame.timeGap + lastFrame.timeGap;
				o.gyr = lastFrame.gyr;
				this.frameHit.push(o);
			} else {
				newFrame.hit = 0;
			}

			if (this.frameHit.length < this.frameHitCapacity && this.frameHit.length != 0) {
				var o = new Object();
				o.time = this.frameHit[this.frameHit.length - 1].time + newFrame.timeGap;
				//o.gyr = this.frameHit[this.frameHit.length-1].gyr.plus(newFrame.gyr);
				o.gyr = newFrame.gyr;
				this.frameHit.push(o);
				if (this.frameHit.length == this.frameHitCapacity) {//累计达到设定的延迟帧数，输出方向
					direction = this.GetDirection();
				}
			}
			if ((this.frameOffset += 1) >= this.frameCapacity) {
				this.frameOffset -= this.frameCapacity;
			}
			return [newFrame.hit, direction];
		}

		getTempValue(curDirection) {
            let result = Math.atan2(curDirection.y,curDirection.x) * 180 / (Math.PI);
            result = Math.round(result);
			let curAngle = result > 0 ? result:(360 + result);
			
			let directionPunch = "all",
				name = "击中",
				ename = "hit";

			if (curAngle < 110 && curAngle >= 70) {
				directionPunch = "straightPunch";
				name = "正向的直拳";
				ename = "front-straight";
			} else if (curAngle < 70 && curAngle >= 0) {
				directionPunch = "rightPunch";
				name = "正向的右拳";
				ename = "front-right";
			} else if (curAngle >= 110 && curAngle <= 180) {
				directionPunch = "leftPunch";
				name = "正向的左拳";
				ename = "front-left";
			}
			//相反方向击打
			//正方向
			else if (curAngle > 180 && curAngle <= 250) {
				directionPunch = "rightPunch";
				name = "负向的右拳";
				ename = "back-right";
			}
			else if (curAngle > 250 && curAngle <= 290) {
				directionPunch = "straightPunch";
				name = "负向的直拳";
				ename = "back-straight";
			} else if (curAngle > 290 && curAngle <= 360) {
				directionPunch = "leftPunch";
				name = "负向的左拳";
				ename = "back-left";
			}


			this.quitHitCount++;

			let temp = {
				type: 'hit',
				hit: curDirection.length,
				hitCount: this.quitHitCount,
				direction: directionPunch,
				directionVect: {
					'x': curDirection.x,
					'y': curDirection.y
				},
				angle: curAngle,
				name: name,
				ename: ename
			}
			return temp;

		}
	}
};