#include "cm_world_sector_private.h"

qboolean
CM_SightTraceStaticModels_r(cmSightTraceStaticModelsWork_t *work,
             worldSector_t *sector,
             float startFraction,
             float endFraction,
             const vec3_t start,
             const vec3_t end)
{
    if ((work->contentsMask &
         sector->sightTraceStaticModelContentsMask) == 0) {
        return 1;
    }

    const int32_t axis = sector->axis;
    const float startDistance = start[axis] - sector->dist;
    const float endDistance = end[axis] - sector->dist;

    if (!(startDistance >= 0.0f) || !(endDistance >= 0.0f)) {
        if (!(0.0f >= startDistance) || !(0.0f >= endDistance)) {
            const float splitFraction =
                startDistance / (startDistance - endDistance);
            const float middleFraction =
                startFraction +
                (endFraction - startFraction) * splitFraction;
            vec3_t middle;
            const uint32_t side = (uint32_t)(startDistance < 0.0f);

            middle[0] = start[0] + (end[0] - start[0]) * splitFraction;
            middle[1] = start[1] + (end[1] - start[1]) * splitFraction;
            middle[2] = start[2] + (end[2] - start[2]) * splitFraction;

            if (CM_SightTraceStaticModels_r(work,
                             CM_LoadWorldSector(sector->children[side]),
                             startFraction,
                             middleFraction,
                             start,
                             middle) == 0) {
                return 0;
            }

            if (CM_SightTraceStaticModels_r(work,
                             CM_LoadWorldSector(sector->children[1 - side]),
                             middleFraction,
                             endFraction,
                             middle,
                             end) == 0) {
                return 0;
            }
        } else if (CM_SightTraceStaticModels_r(work,
                                CM_LoadWorldSector(sector->children[1]),
                                startFraction,
                                endFraction,
                                start,
                                end) == 0) {
            return 0;
        }
    } else if (CM_SightTraceStaticModels_r(work,
                            CM_LoadWorldSector(sector->children[0]),
                            startFraction,
                            endFraction,
                            start,
                            end) == 0) {
        return 0;
    }

    trace_t trace;
    trace.fraction = 1.0f;

    for (worldSectorAreaLink_t *areaLink =
             CM_LoadAreaLink(sector->staticModelLinkHead);
         areaLink != NULL;
         areaLink = CM_LoadAreaLink(areaLink->nextInWorldSector)) {
        if (areaLink->sightTraceEligible != qfalse &&
            (XModelGetContents(areaLink->model) & work->contentsMask) != 0 &&
            CM_TraceLineSkipsBox(work->start,
                                 work->end,
                                 areaLink->linkMins,
                                 areaLink->linkMaxs,
                                 1.0f) == 0) {
            CM_TraceStaticModel(areaLink,
                                &trace,
                                work->start,
                                work->end,
                                work->contentsMask);
            if (trace.fraction != 1.0f) {
                return 0;
            }
        }
    }

    return 1;
}
