import math
from mass3d import Mass3D
from link3d import Link3D
from circle import Circle

class LinkedCircle:
    """
    Class which represents a circle of msd3d masses.  The circle is actually constructed
    from two circles, one with fixed masses and one with floating masses.  The two circles
    (fixed and floating) are linked together.  (If there was only a floating circle it would not
    retain its shape.)  In addition, each floating mass is linked to its neighbour.  Also,
    'collision links' are created so that masses will bounce off each other if they get close
    enough.
    """

    def __init__(self):
        self.diameter = 0.0
        self.mass_count = 0
        self.mass = 0.0
        self.mass_size = 0.0
        self.link_rigidity = 0.0
        self.link_damping = 0.0
        self.collision_link_rigidity = 0.05
        self.mass_messages = []
        self.link_messages = []
    
    def get_mass_setup_messages(self):
        """Returns a list of all msd creation messages for masses"""
        
        return self.mass_messages

    def get_link_setup_messages(self):
        """Returns a list of all msd creation messages for links"""
        
        return self.link_messages

    def create_circle(self, fixed = True, mass_id = "mass", prefix_id = False):
        circle = Circle()
        circle.diameter = self.diameter
        circle.mass_count = self.mass_count
        circle.mass = self.mass
        circle.fixed = fixed
        circle.mass_id = mass_id
        circle.prefix_id = prefix_id
        circle.create_circle()
        
        for message in circle.get_mass_setup_messages():
            self.mass_messages.append(message)
    
    def create_linked_circle(self):
        """Creates two circles with same diameter, one with fixed masses, one with floating."""
        
        self.create_circle(fixed = True, mass_id = "fixed-mass")
        self.create_circle(fixed = False, mass_id = "floating-mass", prefix_id = False)    
        
        for i in range(0, self.mass_count, 1):
            fixed_to_floaty_link = Link3D()
            fixed_to_floaty_link.id = "fixed-to-floaty-link"
            fixed_to_floaty_link.mass1_id = i
            fixed_to_floaty_link.mass2_id = i + self.mass_count
            fixed_to_floaty_link.rigidity = self.link_rigidity
            fixed_to_floaty_link.damping = self.link_damping
            self.link_messages.append(fixed_to_floaty_link.get_msd_setup_message())
            
            #Link every floating mass to its neighbour
            floaty_to_floaty_link = Link3D()
            floaty_to_floaty_link.id = "floaty-to-floaty-link"
            floaty_to_floaty_link.mass1_id = i + self.mass_count
            floaty_to_floaty_link.mass2_id = floaty_to_floaty_link.mass1_id + 1
            floaty_to_floaty_link.rigidity = self.link_rigidity
            floaty_to_floaty_link.damping = self.link_damping
            
            #Link last floating mass back to first one
            if floaty_to_floaty_link.mass2_id >= self.mass_count * 2:
                floaty_to_floaty_link.mass2_id = self.mass_count
            self.link_messages.append(floaty_to_floaty_link.get_msd_setup_message())
        
        collision_link = Link3D()
        collision_link.id = "collision-link"
        collision_link.mass1_id = "floating-mass" 
        collision_link.mass2_id = "floating-mass"
        collision_link.rigidity = self.collision_link_rigidity
        collision_link.damping = 0
        collision_link.distance_exponent = 1
        collision_link.min_length = 0
        collision_link.max_length = self.mass_size
        
        self.link_messages.append(collision_link.get_msd_setup_message())
            
    def create_collision_links(self):
        """Currently unused- may be useful if I decide to use individual names for floating-masses"""
        for i in range(self.mass_count, self.mass_count * 2, 1):
            for j in range(self.mass_count + 1, self.mass_count * 2, 1):
                if j > i:
                    collision_link = Link3D()
                    collision_link.id = "collision-link"
                    collision_link.mass1_id = i
                    collision_link.mass2_id = j
                    collision_link.rigidity = self.collision_link_rigidity
                    collision_link.damping = 0
                    collision_link.distance_exponent = 1
                    collision_link.min_length = 0
                    collision_link.max_length = self.mass_size
                        
                    self.link_messages.append(collision_link.get_msd_setup_message())