from arm.logicnode.arm_nodes import *

class AddRigidBodyNode(ArmLogicTreeNode):
    """Adds a rigid body to an object if not already present. 

    @option Advanced: Shows optional advanced options for rigid body.

    @option Shape: Shape of the rigid body including Box, Sphere, Capsule, Cone, Cylinder, Convex Hull and Mesh
    
    @input Object: Object to which rigid body is added.

    @input Mass: Mass of the rigid body. Must be > 0.

    @input Active: Rigid body actively participates in the physics world and will be affected by collisions

    @input Animated: Rigid body follows animation and will affect other active non-animated rigid bodies.
    
    @input Trigger: Rigid body behaves as a trigger and detects collision. However, rigd body does not contribute to or receive collissions. 
    
    @input Friction: Surface friction of the rigid body. Minimum value = 0, Preferred max value = 1.

    @input Bounciness: How elastic is the surface of the rigid body. Minimum value = 0, Preferred max value = 1.

    @input Continuous Collision Detection (CCD): Detects for collisions in between frames. Use only for very fast moving objects.

    @input Collision Margin: Enable an external margin for collision detection

    @input Margin: Length of the collision margin. Must be > 0.

    @input Linear Damping: Damping for linear translation. Recommended range 0 to 1.

    @input Angular Damping: Damping for angular translation. Recommended range 0 to 1.

    @input Use Deactivation: Deactive this rigid body when below the Linear and Angular velocity threshold. Enable to improve performance.

    @input Linear Velocity Threshold: Velocity below which decativation occurs if enabled.
    
    @input Angular Velocity Threshold: Velocity below which decativation occurs if enabled.

    @input Collision Group: A set of rigid bodies that can interact with each other

    @input Collision Mask: Bitmask to filter collisions. Collision can occur between two rigid bodies if they have atleast one bit in common.

    @output Rigid body: Object to which rigid body was added.

    @output Out: activated after rigid body is added. 
    """
    
    bl_idname = 'LNAddRigidBodyNode'
    bl_label = 'Add Rigid Body'
    arm_version = 1

    NUM_STATIC_INS = 9

    def update_advanced(self, context):
        """This is a helper method to allow declaring the `advanced`
        property before the update_sockets() method. It's not required
        but then you would need to move the declaration of `advanced`
        further down."""
        self.update_sockets(context)

    @property
    def property1(self):
        return 'true' if self.property1_ else 'false'

    property1_: BoolProperty(
        name="Advanced",
        description="Show advanced options",
        default=False,
        update=update_advanced
    )

    property0: EnumProperty(
        items = [('Box', 'Box', 'Box'),
                 ('Sphere', 'Sphere', 'Sphere'),
                 ('Capsule', 'Capsule', 'Capsule'),
                 ('Cone', 'Cone', 'Cone'),
                 ('Cylinder', 'Cylinder', 'Cylinder'),
                 ('Convex Hull', 'Convex Hull', 'Convex Hull'),
                 ('Mesh', 'Mesh', 'Mesh')],
        name='Shape', default='Box')

    def init(self, context):
        super(AddRigidBodyNode, self).init(context)
        
        self.add_input('ArmNodeSocketAction', 'In')
        self.add_input('ArmNodeSocketObject', 'Object')
        self.add_input('NodeSocketFloat', 'Mass', 1.0)
        self.add_input('NodeSocketBool', 'Active', True)
        self.add_input('NodeSocketBool', 'Animated', False)
        self.add_input('NodeSocketBool', 'Trigger', False)
        self.add_input('NodeSocketFloat', 'Friction', 0.5)
        self.add_input('NodeSocketFloat', 'Bounciness', 0.0)
        self.add_input('NodeSocketBool', 'Continuous Collision Detection', False)
        self.add_output('ArmNodeSocketAction', 'Out')
        self.add_output('ArmNodeSocketObject', 'Rigid body')

        self.update_sockets(context)

    def update_sockets(self, context):
        # It's bad to remove from a list during iteration so we use
        # this helper list here
        remove_list = []

        # Remove dynamically placed input sockets
        for i in range(AddRigidBodyNode.NUM_STATIC_INS, len(self.inputs)):
            remove_list.append(self.inputs[i])
        for i in remove_list:
            self.inputs.remove(i)

        # Add dynamic input sockets
        if self.property1_:
            self.add_input('NodeSocketBool', 'Collision Margin', False)
            self.add_input('NodeSocketFloat', 'Margin', 0.04)
            self.add_input('NodeSocketFloat', 'Linear Damping', 0.04)
            self.add_input('NodeSocketFloat', 'Angular Damping', 0.1)
            self.add_input('NodeSocketBool', 'Use Deacivation')
            self.add_input('NodeSocketFloat', 'Linear Velocity Threshold', 0.4)
            self.add_input('NodeSocketFloat', 'Angular Velocity Threshold', 0.5)
            self.add_input('NodeSocketInt', 'Collision Group', 1)
            self.add_input('NodeSocketInt', 'Collision Mask', 1)


    def draw_buttons(self, context, layout):
        layout.prop(self, "property1_")
        layout.prop(self, 'property0')