/*
 * Wall.java
 *
 * This class is a ObstacleSprite referencing a wall. In the physics lab, we
 * had a single class for walls and platforms. In this demo, we have separated
 * them because the JSON specification is different (we only used geometry in
 * the physics lab).
 *
 * Based on the original PhysicsDemo Lab by Don Holden, 2007
 *
 * Author:  Walker M. White
 * Version: 2/14/2025
 */
 package edu.cornell.cis3152.json;

import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.physics.box2d.*;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.JsonValue;
import edu.cornell.gdiac.assets.*;
import edu.cornell.gdiac.math.*;
import edu.cornell.gdiac.physics2.*;

/**
 * A class representing a tiled wall
 *
 * An ObstacleSprite is a sprite (specifically a textured mesh) that is
 * connected to a obstacle. It is designed to be the same size as the
 * physics object, and it tracks the physics object, matching its position
 * and angle at all times.
 *
 * Unlike the physics lab, this object can be resized.
 */
public class Wall extends GameObject {
    /** The default PHYSICS UNITS for this sprite */
    private Poly2 shape;

    /**
     * Creates a Wall with the given physics data and geometry.
     *
     * We assume that all information -- both the geometry and the physics
     * constants -- are stored in the JSON file. The asset directory is used
     * to access the texture.
     *
     * Note that the constructor does NOT build the mesh right away. We need
     * the physics units to build the mesh. As that value is computed
     * separately from the level loading (from the window size), we handle
     * that in the method {@link #setPhysicsUnits(float)}.
     *
     * @param directory the asset manager
     * @param data      The wall geometry and physics constants.
     */
    public Wall(AssetDirectory directory, JsonValue data) {
        float[] points = data.get( "boundary" ).asFloatArray();

        // Construct a Poly2 object, breaking it into triangles
        shape = new Poly2();
        PolyTriangulator triangulator = new PolyTriangulator();
        triangulator.set( points );
        triangulator.calculate();
        triangulator.getPolygon( shape );

        obstacle = new PolygonObstacle( points );
        obstacle.setBodyType( data.get( "bodytype" ).asString().equals( "static" ) ? BodyDef.BodyType.StaticBody : BodyDef.BodyType.DynamicBody );
        obstacle.setDensity( data.getFloat( "density", 0 ) );
        obstacle.setFriction( data.getFloat( "friction", 0 ) );
        obstacle.setRestitution( data.getFloat( "restitution", 0 ) );
        obstacle.setUserData( this );
        obstacle.setName( data.name );

        debug = ParserUtils.parseColor( data.get( "debug_color" ), Color.WHITE );

        setTexture( directory.getEntry( data.getString( "texture" ), Texture.class ) );
    }

    /**
     * Sets the physics units for this game object.
     *
     * Setting the physics objects build the mesh for this object. This method
     * should be called whenever the window size changes to resize the meshes
     * for the new display.
     *
     * @param units The physics units for this object
     */
    public void setPhysicsUnits(float units) {
        obstacle.setPhysicsUnits(units);

        // Create a polygon mesh matching the physics body, adjusted by the
        // physics units. We take the save polygon we used to create the
        // physics obstacle and scale it up. We then use that to set the
        // mesh. The attribute tile is used to define how we scale/stretch
        // the texture to fit to the polygon. Try experimenting with this in
        // the JSON to see what happens.
        Poly2 poly = new Poly2(shape);
        poly.scl( units );

        float tile = getSpriteSheet().getRegionWidth();
        mesh.set(poly,tile,tile);
    }


}
