#ifndef SPHERE_H
#define SPHERE_H

#include <cmath>
#include <glm/glm.hpp>
#include <vector>

struct SphereVertex {
  glm::vec3 position;
  glm::vec3 normal;   // Fixed: Must be vec3 for 3D directions
  glm::vec2 texCoord; // Fixed: Must be vec2 for U,V coordinates
};

// Generates vertex and index data for a sphere
inline void generateSphere(float radius, int sectors, int stacks,
                           std::vector<SphereVertex> &vertices,
                           std::vector<unsigned int> &indices) {
  vertices.clear();
  indices.clear();

  float x, y, z, xy;
  float nx, ny, nz, lengthInv = 1.0f / radius;
  float s, t;

  float sectorStep = 2 * M_PI / sectors;
  float stackStep = M_PI / stacks;
  float sectorAngle, stackAngle;

  for (int i = 0; i <= stacks; ++i) {
    stackAngle = M_PI / 2 - i * stackStep;
    xy = radius * std::cos(stackAngle);
    z = radius * std::sin(stackAngle);

    for (int j = 0; j <= sectors; ++j) {
      sectorAngle = j * sectorStep;

      // Position
      x = xy * std::cos(sectorAngle);
      y = xy * std::sin(sectorAngle);

      SphereVertex vertex;
      vertex.position = glm::vec3(x, y, z);
      // Normal is just the normalized position for a sphere at origin
      vertex.normal = glm::vec3(x * lengthInv, y * lengthInv, z * lengthInv);
      vertex.texCoord = glm::vec2((float)j / sectors, (float)i / stacks);

      vertices.push_back(vertex);
    }
  }

  // Index generation: connecting the stacks and sectors
  for (int i = 0; i < stacks; ++i) {
    int k1 = i * (sectors + 1);
    int k2 = k1 + sectors + 1;
    for (int j = 0; j < sectors; ++j, ++k1, ++k2) {
      if (i != 0) {
        indices.push_back(k1);
        indices.push_back(k2);
        indices.push_back(k1 + 1);
      }
      if (i != (stacks - 1)) {
        indices.push_back(k1 + 1);
        indices.push_back(k2);
        indices.push_back(k2 + 1);
      }
    }
  }
}

#endif
