import CompuCell, CompuCellSetup, PlayerPython
from PySteppables import SteppableBasePy
from math import sqrt
import time
import random           
            
class CellPropertyandModifier(SteppableBasePy):
    def __init__(self,_simulator,_frequency=50):
        SteppableBasePy.__init__(self,_simulator,_frequency)
        
    def start(self):
        for cell in self.cellList:          #### initializing color property
            cell.targetVolume=25
            cell.lambdaVolume=10
            cell.targetSurface=4*sqrt(cell.targetVolume)
            cell.lamdaSurface=10
            
            cell_attributes=CompuCell.getPyAttrib(cell)
            cell_attributes['property red']=False
            cell_attributes['property green']=False
            cell_attributes['property blue']=False
            
    def step(self,mcs):
        for cell in self.cellList:
            cell_attributes=CompuCell.getPyAttrib(cell)
            cell_attributes['property green']=False
            cell_attributes['property blue']=False
############Begin code for simulations without apoptosis
            if random.random()<.5:
                cell_attributes['property green']=True
            else:
                cell_attributes['property blue']=True
############End code for simulations without apoptosis


class CellTypeVisualizer(SteppableBasePy):
    def __init__(self,_simulator,_frequency=50):
        SteppableBasePy.__init__(self,_simulator,_frequency)
        self.runBeforeMCS=True
        
    def start(self):
        self.cellTypeField=CompuCellSetup.createScalarFieldCellLevelPy("CellPropertyField")
        
    def step(self,mcs):
        PlayerPython.clearScalarValueCellLevel(self.cellTypeField)
        for cell in self.cellList:
            cell_attributes=CompuCell.getPyAttrib(cell)
            if cell_attributes['property red']==True:
                PlayerPython.fillScalarValueCellLevel(self.cellTypeField,cell,2.0)
            elif cell_attributes['property green']==True:
                PlayerPython.fillScalarValueCellLevel(self.cellTypeField,cell,1.0)
            elif cell_attributes['property blue']==True: ### could use just "else"
                PlayerPython.fillScalarValueCellLevel(self.cellTypeField,cell,0.01)




class ApoptosisCheck(SteppableBasePy):
    def __init__(self,_simulator,_frequency=10):
        SteppableBasePy.__init__(self,_simulator,_frequency)
        
    def start(self):
        for cell in self.cellList:              #### initializing apoptotic property
            cell_attributes=CompuCell.getPyAttrib(cell)
            cell_attributes['property red']=False
            
    def step(self,mcs):
        for cell in self.cellList:
            cell_attributes=CompuCell.getPyAttrib(cell)
            if cell_attributes['property red']==False and random.random()>.9995:
                cell_attributes['property green']=False
                cell_attributes['property blue']=False
                cell_attributes['property red']=True                



class Apoptosis(SteppableBasePy):
    def __init__(self,_simulator,_frequency=10):
        SteppableBasePy.__init__(self,_simulator,_frequency)
        self.mitosisSteppable=CompuCell.MitosisSteppable()
        self.mitosisSteppable.init(_simulator)
        
    def step(self,mcs):
        self.randomcelldivisionlist=[]
        target_total_cell_volume=0
        actual_total_cell_volume=0
        for cell in self.cellList:
            cell_attributes=CompuCell.getPyAttrib(cell)
            if cell_attributes['property red']==True and cell.volume>6:
                self.randomcelldivisionlist.append(cell)
                
        for dividecell in self.randomcelldivisionlist:
            if self.mitosisSteppable.doDirectionalMitosisRandomOrientation(dividecell):
                self.updateAttributes()
            
##    def step(self,mcs):
##        self.randomcelldivisionlist=[]
##        [self.randomcelldivisionlist.append(cell) for cell in self.cellList if (CompuCell.getPyAttrib(cell)['apoptotic']==True and cell.volume>7)]
##        [self.updateAttributes() for dividecell in self.randomcelldivisionlist if self.mitosisSteppable.doDirectionalMitosisRandomOrientation(dividecell)]
        
    def updateAttributes(self):
        childCell=self.mitosisSteppable.childCell
        parentCell=self.mitosisSteppable.parentCell
        parentCell.targetVolume=parentCell.targetVolume/2
        childCell.targetVolume=parentCell.targetVolume
        parentCell.targetSurface=4*sqrt(parentCell.targetVolume)
        childCell.targetSurface=4*sqrt(childCell.targetVolume)
        childCell.lambdaVolume=parentCell.lambdaVolume
        childCell.lambdaSurface=parentCell.lambdaSurface
        childCell.type=parentCell.type
        CompuCell.getPyAttrib(childCell).update(CompuCell.getPyAttrib(parentCell))



class PropertySwitcher(SteppableBasePy):
    def __init__(self,_simulator,_frequency=10):
        SteppableBasePy.__init__(self,_simulator,_frequency)

    def step(self,mcs):
        for cell in self.cellList:
            cell_attributes=CompuCell.getPyAttrib(cell)
            if cell_attributes['property red']==True:
                cell.type=2



class Output(SteppableBasePy):
    def __init__(self,_simulator,_frequency=10):
        SteppableBasePy.__init__(self,_simulator,_frequency)

    def step(self,mcs):
        x=time.clock()
        target_total_cell_volume=0
        actual_total_cell_volume=0
        for cell in self.cellList:
            target_total_cell_volume+=cell.targetVolume
            actual_total_cell_volume+=cell.volume
        print "Output,               Time Taken=", time.clock()-x
        print " Total Target Volume is: ", target_total_cell_volume
        print " Total Actual Volume is: ", actual_total_cell_volume

        
class MassConservationViaMacrophage(SteppableBasePy):       
    def __init__(self,_simulator,_frequency=10):
        SteppableBasePy.__init__(self,_simulator,_frequency)
    def step(self,mcs):
        for cell in self.cellList:
            cell_attributes=CompuCell.getPyAttrib(cell)
            if cell_attributes['property red']==True and cell.volume<=6:
                neighborchoice=random.choice(list(self.getCellNeighbors(cell)))
                if neighborchoice.neighborAddress and CompuCell.getPyAttrib(neighborchoice.neighborAddress)['property green']==True:
                    neighbor_attributes=CompuCell.getPyAttrib(neighborchoice.neighborAddress)
                    if neighbor_attributes['property red']!=True:
                        neighborchoice.neighborAddress.targetVolume+=cell.targetVolume
                        neighborchoice.neighborAddress.targetSurface=4*sqrt(neighborchoice.neighborAddress.targetVolume)
                        cell.targetVolume=0
                        cell.targetSurface=0
        

class Mitosis(SteppableBasePy):
    def __init__(self,_simulator,_frequency=10):
        SteppableBasePy.__init__(self,_simulator,_frequency)
        self.mitosisSteppable=CompuCell.MitosisSteppable()
        self.mitosisSteppable.init(_simulator)
        
    def step(self,mcs):
        self.randomcelldivisionlist=[]
        for cell in self.cellList:
            cell_attributes=CompuCell.getPyAttrib(cell)
            if cell_attributes['property red']!=True and cell.volume>100:
                self.randomcelldivisionlist.append(cell)
        for dividecell in self.randomcelldivisionlist:
            if self.mitosisSteppable.doDirectionalMitosisRandomOrientation(dividecell):
                self.updateAttributes() 

    def updateAttributes(self):
        childCell=self.mitosisSteppable.childCell
        parentCell=self.mitosisSteppable.parentCell
        parentCell.targetVolume=parentCell.targetVolume/2
        childCell.targetVolume=parentCell.targetVolume
        parentCell.targetSurface=4*sqrt(parentCell.targetVolume)
        childCell.targetSurface=4*sqrt(childCell.targetVolume)
        childCell.lambdaVolume=parentCell.lambdaVolume
        childCell.lambdaSurface=parentCell.lambdaSurface
        childCell.type=parentCell.type
        CompuCell.getPyAttrib(childCell).update(CompuCell.getPyAttrib(parentCell))

