#pragma once

#include "../utils/flags.hpp"
#include "./math.hpp"
#include "./Box.hpp"

namespace geometry {

enum class Shape {
    Cube,
    Sphere
};

struct Volume {
    Shape shape;
    int radius;


    /// AABB bounding box
    template<typename U>
    _FORCE_INLINE_ AABB<U> getBoundingBox(const glm::vec<3, U>& center) const {
        return AABB<U>::FromCenter(center, glm::vec<3, U>(radius));
    }

    /// AABB bounding box after rotation
    template<typename U>
    _FORCE_INLINE_ AABB<U> getBoundingBox(const glm::vec<3, U>& center, const glm::quat& pivot) const {
        switch (shape) {
        case Shape::Cube:
            return AABB<U>::FromCenter(center, glm::vec<3, U>(radius), pivot);

        case Shape::Sphere:
            return getBoundingBox(center);
        }
    }

    /// Volume intersect or contains box
    template<typename U>
    _FORCE_INLINE_ bool intersects(const glm::vec<3, U>& center, const AABB<U>& box) const {
        switch (shape) {
        case Shape::Cube:
            return AABB<U>::FromCenter(center, glm::vec<3, U>(radius)).intersects(box);

        case Shape::Sphere:
            return box.intersected(center, radius);

        default:
            return false;
        }
    }

    /// Volume intersect or contains box
    template<typename U, typename P>
    _FORCE_INLINE_ bool intersects(const glm::vec<3, U>& center, const OBB<U, P>& box) const {
        switch (shape) {
        case Shape::Cube:
            return AABB<U>::FromCenter(center, glm::vec<3, U>(radius)).intersects(box);

        case Shape::Sphere:
            return box.intersected(center, radius);

        default:
            return false;
        }
    }

    /// Volume intersect or contains box after rotation
    template<typename U, typename P>
    _FORCE_INLINE_ bool intersects(const glm::vec<3, U>& center, const glm::quat& pivot, const OBB<U, P>& box) const {
        switch (shape) {
        case Shape::Cube:
            return OBB<U, P>::FromCenter(center, glm::vec<3, U>(radius), pivot).intersects(box);

        case Shape::Sphere:
            return box.intersected(center, radius);

        default:
            return false;
        }
    }
};

};
