#ifndef INFERNO_DEFINITIONS_PRIMATIVES_PRIMATIVE_H_
#define INFERNO_DEFINITIONS_PRIMATIVES_PRIMATIVE_H_

#include "../materials/material.hpp"
#include "../materials/texture.hpp"

#include "../../maths.hpp"

class Ray;

enum PrimativeType {
    TYPE_NONE,
    TYPE_SPHERE,
    TYPE_PLANE,
    TYPE_TRI
};

class Primative {
public:
    // Attributes
    glm::vec3 center;
    //      Sphere
    float radius;
    //      Plane
    glm::vec3 normal;
    //      Triangle
    glm::vec3 points[3];
    glm::vec3 normals[3];

	Material* material = nullptr;

    PrimativeType type = TYPE_NONE;

    // Sphere constructor
    Primative(glm::vec3 center, float radius, Material* mat) 
        : center(center), radius(radius) { 
        type = TYPE_SPHERE;
		material = mat;
    }

    // Plane constructor
    Primative(glm::vec3 center, glm::vec3 normal, Material* mat)
        : center(center), normal(normal) {
        type = TYPE_PLANE;
		material = mat;
    }

    // Triangle constructor
    Primative(glm::vec3 p0, glm::vec3 p1, glm::vec3 p2, glm::vec3 n0, glm::vec3 n1, glm::vec3 n2, Material* mat) {
		points[0] = p0; points[1] = p1; points[2] = p2;
        normals[0] = n0; normals[1] = n1; normals[2] = n2;
        type = TYPE_TRI;
		material = mat;
    }

    virtual bool Intersect(Ray& ray, float& t) = 0;
	virtual glm::vec3 SurfaceNormal(glm::vec3 hitPoint) = 0;
	virtual glm::vec3 SurfaceTangent(glm::vec3 normal) = 0;
	virtual glm::vec2 TexCoords(glm::vec3 hitPoint) = 0;
	virtual void Translate(glm::vec3 trans) = 0;

	inline glm::vec3 Normal(glm::vec3 hitPoint) {
		if (material == nullptr) return SurfaceNormal(hitPoint);
		if (material->NormalTexture == nullptr) return SurfaceNormal(hitPoint);

		return material->NormalTexture->SampleNormal(TexCoords(hitPoint));

		// combine with surface normal


	}
};

#endif
