import { vec2 } from '../math/vec2';
import { Ray } from '../collision/Ray';
import { Shape } from "../shapes/Shape";

/**
 * 记录射线碰撞结果
 * 主要有normal,shape,body,faceIndex,fraction
 * 还有方法等
 */
export class RaycastResult {
	/**
	 * 碰撞点的法向量,在全局内
	 * The normal of the hit, oriented in world space.
	 * @property {array} normal
	 */
	normal: Float32Array;
	/**
	 * The hit shape, or null.
	 * @property {Shape} shape
	 */
	shape: Shape;
	/**
	 * The hit body, or null.
	 * @property {Body} body
	 */
	body: any;
	/**
	 * shape中的三角形索引
	 * The index of the hit triangle, if the hit shape was indexable.
	 * @property {number} faceIndex
	 * @default -1
	 */
	faceIndex: number;
	/**
	 * 0靠近起点,1靠近终点
	 * Distance to the hit, as a fraction. 0 is at the "from" point, 1 is at the "to" point. Will be set to -1 if there was no hit yet.
	 * @property {number} fraction
	 * @default -1
	 */
	fraction: number;
	/**
	 * 是否穿透
	 * If the ray should stop traversing.
	 * @readonly
	 * @property {Boolean} isStopped
	 */
	isStopped: boolean;
	/**
	 * Storage for Ray casting hit data.
	 * @class RaycastResult
	 * @constructor
	 */
	constructor() {


		this.normal = vec2.create();


		this.shape = null;


		this.body = null;


		this.faceIndex = -1;


		this.fraction = -1;


		this.isStopped = false;
	}

	/**
	 * 重置
	 * Reset all result data. Must be done before re-using the result object.
	 * @method reset
	 */
	reset() {
		vec2.set(this.normal, 0, 0);
		this.shape = null;
		this.body = null;
		this.faceIndex = -1;
		this.fraction = -1;
		this.isStopped = false;
	};

	/**
	 * 获取到碰撞点的距离
	 * Get the distance to the hit point.
	 * @method getHitDistance
	 * @param {Ray} ray
	 * @return {number}
	 */
	getHitDistance(ray:Ray) {
		return vec2.distance(ray.from, ray.to) * this.fraction;
	};

	/**
	 * 是否碰撞
	 * Returns true if the ray hit something since the last reset().
	 * @method hasHit
	 * @®eturn {boolean}
	 */
	hasHit() {
		return this.fraction !== -1;
	};

	/**
	 * 获取全局碰撞点
	 * Get world hit point.
	 * @method getHitPoint
	 * @param {array} out 输出量
	 * @param {Ray} ray
	 */
	getHitPoint(out, ray) {
		vec2.lerp(out, ray.from, ray.to, this.fraction);
	};

	/**
	 * 停止继续寻找碰撞点
	 * Can be called while iterating over hits to stop searching for hit points.
	 * @method stop
	 */
	stop() {
		this.isStopped = true;
	};

	/**
	 * @method shouldStop
	 * @private
	 * @param {Ray} ray
	 * @return {boolean}
	 */
	shouldStop(ray) {
		return this.isStopped || (this.fraction !== -1 && ray.mode === Ray.ANY);
	};

	/**
	 * @method set
	 * @private
	 * @param {array} normal
	 * @param {Shape} shape
	 * @param {Body} body
	 * @param {number} fraction
	 * @param {number} faceIndex
	 */
	set(
		normal,
		shape,
		body,
		fraction,
		faceIndex
	) {
		vec2.copy(this.normal, normal);
		this.shape = shape;
		this.body = body;
		this.fraction = fraction;
		this.faceIndex = faceIndex;
	};
}