/*
 * Door.java
 *
 * This is a refactored version of the "win door" that allows us to read ALL of
 * its properties from a JSON file. While we did do a lot of that in the physics
 * lab, we still hard-coded things like textures. This time, everything is
 * defined in the JSON file and parsed in this class.
 *
 * 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.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.utils.JsonValue;
import edu.cornell.gdiac.assets.AssetDirectory;
import edu.cornell.gdiac.assets.ParserUtils;
import edu.cornell.gdiac.physics2.BoxObstacle;
import edu.cornell.gdiac.physics2.ObstacleSprite;

/**
 * The win door.
 *
 * 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.
 *
 * The associated obstacle is ALWAYS sensor (this is not an option to specify
 * in the JSON). That means that collisions will be detected, but nothing
 * happens to the game physics. Instead, we decide the result of the collision.
 *
 * Unlike the physics lab, this object can be resized.
 */
public class Door extends GameObject {
    /** The width of the door in box2d units */
    private float width;
    /** The height of the door in box2d units */
    private float height;

    /**
     * Creates a door with the given physics units and settings
     *
     * The physics units are used to size the mesh relative to the physics
     * body. All other attributes are defined by the JSON file
     *
     * @param units     The physics units
     * @param settings  The door physics constants
     */
    public Door(AssetDirectory directory, JsonValue data) {
        super();

        float x = data.get("pos").getFloat(0);
        float y = data.get("pos").getFloat(1);
        width = data.get( "size" ).getFloat(0);
        height = data.get( "size" ).getFloat(1);

        obstacle = new BoxObstacle(x, y, width, height);

        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.setSensor( true );
        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);
        mesh.clear();

        // Create a rectangular mesh the same size as the door, adjusted by
        // the physics units. For all meshes attached to a physics body, we
        // want (0,0) to be in the center of the mesh. So the method call below
        // is (x,y,w,h) where x, y is the bottom left.
        mesh.set(-width*units/2.0f,-height*units/2.0f,width*units,height*units);
    }
}
