import { Shape } from './Shape'
import { vec2 } from '../math/vec2'
import { Utils } from '../utils/Utils';


var intersectPlane_planePointToFrom = vec2.create();
var intersectPlane_normal = vec2.create();
var intersectPlane_len = vec2.create();
/**
 * 
 * Plane shape class. The plane is facing in the Y direction.
 * @class Plane
 * @extends Shape
 * @constructor
 * @param {object} [options] (Note that this options object will be passed on to the {{#crossLink "Shape"}}{{/crossLink}} constructor.)
 * @example
 *     var body = new Body();
 *     var shape = new Plane();
 *     body.addShape(shape);
 */
export class Plane extends Shape {
    constructor(options) {
        options = options ? Utils.shallowClone(options) : {};
        options.type = Shape.PLANE;
        super(options);

        this.updateBoundingRadius();
        this.updateArea();
    }

    /**
     * Compute moment of inertia
     * @method computeMomentOfInertia
     */
    computeMomentOfInertia() {
        return 0; // Plane is infinite. The inertia should therefore be infinty but by convention we set 0 here
    };

    /**
     * Update the bounding radius
     * @method updateBoundingRadius
     */
    updateBoundingRadius() {
        this.boundingRadius = Number.MAX_VALUE;
    };

    /**
     * @method computeAABB
     * @param  {AABB}   out
     * @param  {Array}  position
     * @param  {Number} angle
     */
    computeAABB(out, position, angle) {
        var a = angle % (2 * Math.PI);
        var set = vec2.set;
        var max = 1e7;
        var lowerBound = out.lowerBound;
        var upperBound = out.upperBound;

        // Set max bounds
        set(lowerBound, -max, -max);
        set(upperBound, max, max);

        if (a === 0) {
            // y goes from -inf to 0
            upperBound[1] = position[1];

        } else if (a === Math.PI / 2) {

            // x goes from 0 to inf
            lowerBound[0] = position[0];

        } else if (a === Math.PI) {

            // y goes from 0 to inf
            lowerBound[1] = position[1];

        } else if (a === 3 * Math.PI / 2) {

            // x goes from -inf to 0
            upperBound[0] = position[0];

        }
    };

    updateArea() {
        this.area = Number.MAX_VALUE;
    };



    /**
     * @method raycast
     * @param  {RayResult} result
     * @param  {Ray} ray
     * @param  {array} position
     * @param  {number} angle
     */
    raycast(result, ray, position, angle) {
        var from = ray.from;
        var to = ray.to;
        var direction = ray.direction;
        var planePointToFrom = intersectPlane_planePointToFrom;
        var normal = intersectPlane_normal;
        var len = intersectPlane_len;

        // Get plane normal
        vec2.set(normal, 0, 1);
        vec2.rotate(normal, normal, angle);

        vec2.subtract(len, from, position);
        var planeToFrom = vec2.dot(len, normal);
        vec2.subtract(len, to, position);
        var planeToTo = vec2.dot(len, normal);

        if (planeToFrom * planeToTo > 0) {
            // "from" and "to" are on the same side of the plane... bail out
            return;
        }

        if (vec2.squaredDistance(from, to) < planeToFrom * planeToFrom) {
            return;
        }

        var n_dot_dir = vec2.dot(normal, direction);

        vec2.subtract(planePointToFrom, from, position);
        var t = -vec2.dot(normal, planePointToFrom) / n_dot_dir / ray.length;

        ray.reportIntersection(result, t, normal, -1);
    };

    pointTest(localPoint) {
        return localPoint[1] <= 0;
    };
}
