/*
 * Ellipse.java
 *
 * Elliptical-shaped model to support collisions.
 *
 * Sometimes you want ellipses instead of boxes. There is no ellipse shape; you
 * have to build one with polygons. Unfortunately, there is a limit on the
 * number of vertices in a Box2D polygon.  That limit is 8.  So if you want
 * something smoother, you either need to use a circle (same width and height),
 * or you need to build the ellipse from multiple polygons like we did with
 * PolygonObstacle in Lab 4.
 *
 * @author Walker M. White
 * @version 3/9/2025
 */
package edu.cornell.cis3152.box2d.shape;

import com.badlogic.gdx.math.*;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.physics.box2d.*;

import edu.cornell.cis3152.box2d.*;  // For Entity
import edu.cornell.gdiac.math.Poly2;

/**
 * An elliptical physics object.
 */
public class Ellipse extends Entity {
	/** Number of polygon edges to use */
	private static final int NUM_EDGES = 8; // APPEARS TO BE THE BOX2D MAXIMUM

	/** Shape information for this ellipse */
	protected PolygonShape shape;

	/**
	 * Creates a new ellipse, but do not initialize it yet.
	 */
	public Ellipse() {}

	/**
	 * Returns an array of vertices representing an ellipse
	 *
	 * This array is used for both physics AND drawing.
	 *
	 * @return an array of vertices representing an ellipse
	 */
	private float[] makeEllipse(Vector2 size) {
		// Make the ellipse centered at origin
		float stepSize = 2*(float)Math.PI / NUM_EDGES;

		float[] vertices = new float[2*NUM_EDGES];
		float xRadius = size.x / 2.0f;
		float yRadius = size.y / 2.0f;
		for (int ii = 0; ii < NUM_EDGES; ii++) {
			double angle =  stepSize * ii;
			vertices[2*ii  ] = (float)Math.cos(angle) * xRadius;
			vertices[2*ii+1] = (float)Math.sin(angle) * yRadius;
		}

		return vertices;
	}

	/**
     * Creates the collision shape information
     *
     * @param size The object bounding box
     */
	protected void makeFixture(Vector2 size) {
		shape = new PolygonShape();
		shape.set(makeEllipse(size));

		// Create the fixture
		FixtureDef def = new FixtureDef();
		def.density = density;
		def.friction = friction;
		def.restitution = restitution;
		def.shape = shape;

		fixture = body.createFixture(def);
		shape.dispose(); // Do not need it anymore
	}

	/**
     * Creates the drawing shape information
     *
     * @param size  The object bounding box
     */
	protected void makeGraphics(Vector2 size) {
		poly = new Poly2(makeEllipse( size ));
        poly.scl( units );
        poly.indices.ensureCapacity( 3 * (NUM_EDGES-2) );
		for (int ii = 0; ii < NUM_EDGES - 2; ii++) {
			poly.indices.items[3 * ii] = 0;
            poly.indices.items[3 * ii + 1] = (short)(ii + 1);
            poly.indices.items[3 * ii + 2] = (short)(ii + 2);
		}
        poly.indices.size = 3 * (NUM_EDGES-2);
    }
}
