#include "structs.h"
#include "math.h"
#include "helper.h"
#include "vectorOp.h"

vec3 collisionPointSphere(ray *lightray, sphere *object)
{
    vec3 collisionPoint;
    collisionPoint.x = -10000000;
    collisionPoint.y = -10000000;
    collisionPoint.z = -10000000;
    double a = lightray->direction.x * lightray->direction.x + lightray->direction.y * lightray->direction.y + lightray->direction.z * lightray->direction.z;
    double b = 2 * ((lightray->direction.x * (lightray->origin.x - object->origin.x)) + (lightray->direction.y * (lightray->origin.y - object->origin.y)) + (lightray->direction.z * (lightray->origin.z - object->origin.z)));
    double c = (lightray->origin.x * lightray->origin.x + object->origin.x * object->origin.x - 2 * lightray->origin.x * object->origin.x)
    + (lightray->origin.y * lightray->origin.y + object->origin.y * object->origin.y - 2 * lightray->origin.y * object->origin.y)
    + (lightray->origin.z * lightray->origin.z + object->origin.z * object->origin.z - 2 * lightray->origin.z * object->origin.z)
    - object->radius * object->radius;
    double discriminant = b * b - 4 * a * c;
    if (discriminant < 0) return collisionPoint;
    if (discriminant > 0) {
        double S = (-b - sqrt(discriminant)) / (2 * a);
        if (S < 0) return collisionPoint;
        collisionPoint.x = S * lightray->direction.x + lightray->origin.x;
        collisionPoint.y = S * lightray->direction.y + lightray->origin.y;
        collisionPoint.z = S * lightray->direction.z + lightray->origin.z;
        if (!epsilonCheck(lightray->origin, collisionPoint)) {
            return (vec3){-10000000, -10000000, -10000000};
        }

        return collisionPoint;
    }
    double S = (-b)/(2*a);
    if (S < 0) return collisionPoint;
    collisionPoint.x = S * lightray->direction.x + lightray->origin.x;
    collisionPoint.y = S * lightray->direction.y + lightray->origin.y;
    collisionPoint.z = S * lightray->direction.z + lightray->origin.z;
    return collisionPoint;
}

vec3 collisionPlane(ray *lightray, plane *object) {
    vec3 collisionPoint;
    double r;

    if (vec3Product(lightray->direction, object->normal) >= 0) return (vec3){-10000000, -10000000, -10000000};

    r = vec3Product(object->normal, vec3Subtract(object->origin, lightray->origin)) * 1/(vec3Product(lightray->direction, object->normal));
    if (r <= 1e-6) return (vec3){-10000000, -10000000, -10000000};

    collisionPoint = vec3Add(lightray->origin, vec3Scale(lightray->direction, r));
    return collisionPoint;
}

vec3 collisionQuad(ray *lightray, quad *object) {
    vec3 collisionPoint;
    plane Plane = (plane){object->origin, object->normal};
    collisionPoint = collisionPlane(lightray, &Plane);

    if (collisionPoint.x <= -1000000) return collisionPoint;
    if (epsilonCheck(lightray->origin, collisionPoint) == 0) return (vec3){-10000000, -10000000, -10000000};

    vec3 localCollisionPoint = vec3Subtract(collisionPoint, object->origin);

    double scalar1 = vec3Product(object->v1,localCollisionPoint);
    double scalar2 = vec3Product(object->v2,localCollisionPoint);
    if (scalar1 < 0 || scalar2 < 0) return (vec3){-10000000, -10000000, -10000000};

    double scalarSelf1 = vec3Product(object->v1,object->v1);
    double scalarSelf2 = vec3Product(object->v2,object->v2);


    if (scalar1 / scalarSelf1 > 1 || scalar2 / scalarSelf2 > 1) return (vec3){-10000000, -10000000, -10000000};

    return collisionPoint;




}