#include "cm_trace_core_private.h"

void CM_TestBoxInBrush(traceWork_t *traceWork,
                        const coduo_collision_brush_t *brush)
{
    if (traceWork->bounds[0][0] > brush->maxs[0]) {
        return;
    }
    if (traceWork->bounds[0][1] > brush->maxs[1]) {
        return;
    }
    if (traceWork->bounds[0][2] > brush->maxs[2]) {
        return;
    }
    if (brush->mins[0] > traceWork->bounds[1][0]) {
        return;
    }
    if (brush->mins[1] > traceWork->bounds[1][1]) {
        return;
    }
    if (brush->mins[2] > traceWork->bounds[1][2]) {
        return;
    }

    const coduo_collision_brush_side_t *side = brush->sides;
    int32_t sideCount = brush->numSides;

    if (traceWork->sphere.use != 0) {
        for (; sideCount != 0; --sideCount, ++side) {
            const cplane_t *plane = side->plane;
            const float planeDist = plane->dist + traceWork->sphere.radius;
            const float sphereOffset =
                ((plane->normal[0] * traceWork->sphere.offset[0]) +
                 (plane->normal[1] * traceWork->sphere.offset[1])) +
                (plane->normal[2] * traceWork->sphere.offset[2]);
            vec3_t testPoint;

            if (sphereOffset > 0.0f) {
                testPoint[0] =
                    traceWork->start[0] - traceWork->sphere.offset[0];
                testPoint[1] =
                    traceWork->start[1] - traceWork->sphere.offset[1];
                testPoint[2] =
                    traceWork->start[2] - traceWork->sphere.offset[2];
            } else {
                testPoint[0] =
                    traceWork->start[0] + traceWork->sphere.offset[0];
                testPoint[1] =
                    traceWork->start[1] + traceWork->sphere.offset[1];
                testPoint[2] =
                    traceWork->start[2] + traceWork->sphere.offset[2];
            }

            const float distance =
                (((testPoint[0] * plane->normal[0]) +
                  (testPoint[1] * plane->normal[1])) +
                 (testPoint[2] * plane->normal[2])) -
                planeDist;
            if (distance > 0.0f) {
                return;
            }
        }
    } else {
        for (; sideCount != 0; --sideCount, ++side) {
            const cplane_t *plane = side->plane;
            const float *offset = traceWork->offsets[plane->signbits];
            const float planeDist =
                plane->dist -
                (((offset[0] * plane->normal[0]) +
                  (offset[1] * plane->normal[1])) +
                 (offset[2] * plane->normal[2]));
            const float distance =
                (((traceWork->start[0] * plane->normal[0]) +
                  (traceWork->start[1] * plane->normal[1])) +
                 (traceWork->start[2] * plane->normal[2])) -
                planeDist;
            if (distance > 0.0f) {
                return;
            }
        }
    }

    traceWork->trace.allsolid = 1;
    traceWork->trace.startsolid = 1;
    traceWork->trace.fraction = 0.0f;
    traceWork->trace.contents = brush->contents;
}
