#pragma once

#include <glm/glm.hpp>

namespace geometry {
    /// Axis Aligned Long Box
    struct IBox {
        using pos_t = glm::llvec3;
        enum class ContainmentType {
            Disjoint = false, Intersects, Contains
        };

        IBox(pos_t min, pos_t max): Min(min), Max(max) {
            assert((max.x >= min.x && max.y >= min.y && max.z >= min.z) && "Min > Max");
        }
        inline static IBox fromCenter(pos_t center, pos_t::value_type radius) { return IBox(center - radius, center + radius); }
        inline static IBox fromMin(pos_t min, pos_t size) { return IBox(min, min + size); }

        pos_t Min;
        pos_t Max;

        ContainmentType contains(const IBox& box) const {
            //test if all corner is in the same side of a face by just checking min and max
            if (box.Max.x < Min.x
                || box.Min.x > Max.x
                || box.Max.y < Min.y
                || box.Min.y > Max.y
                || box.Max.z < Min.z
                || box.Min.z > Max.z)
                return ContainmentType::Disjoint;


            if (box.Min.x >= Min.x
                && box.Max.x <= Max.x
                && box.Min.y >= Min.y
                && box.Max.y <= Max.y
                && box.Min.z >= Min.z
                && box.Max.z <= Max.z)
                return ContainmentType::Contains;

            return ContainmentType::Intersects;
        }
        constexpr bool contains(const pos_t& pos) const {
            return pos.x >= Min.x && pos.x <= Max.x &&
                   pos.y >= Min.y && pos.y <= Max.y &&
                   pos.z >= Min.z && pos.z <= Max.z;
        }
    };
}