"""

Description: This file defines the class that acts as a template for creating a myelinated collateral.
             It is based on works of Scurfield and Latimer (2018), which in turn is based on a model by Gow and Devaux (2008).

Edit History: Created by Nilapratim Sengupta in July-August 2023.

"""

# Import statements
from neuron import h

# Defining the class
class CollateralTemplate:

    def __init__(self, noOfSegments_collateral):
        
        # Defining number of sections
        self.noOfSegments_collateral = noOfSegments_collateral
        self.noOfNodes_collateral = (noOfSegments_collateral + 1)
        self.noOfParanodeSets_collateral = (noOfSegments_collateral * 2)
        self.noOfJuxtaparanodeSets_collateral = (noOfSegments_collateral * 2)
        self.noOfInternodes_collateral = noOfSegments_collateral

        # Creating sections
        self.nodes_collateral = [h.Section(name=f'nodes_collateral[{loopCounter}]') for loopCounter in range(self.noOfNodes_collateral)]
        self.paranodeOnes_collateral = [h.Section(name=f'paranodeOnes_collateral[{loopCounter}]') for loopCounter in range(self.noOfParanodeSets_collateral)]
        self.paranodeTwos_collateral = [h.Section(name=f'paranodeTwos_collateral[{loopCounter}]') for loopCounter in range(self.noOfParanodeSets_collateral)]
        self.paranodeThrees_collateral = [h.Section(name=f'paranodeThrees_collateral[{loopCounter}]') for loopCounter in range(self.noOfParanodeSets_collateral)]
        self.paranodeFours_collateral = [h.Section(name=f'paranodeFours_collateral[{loopCounter}]') for loopCounter in range(self.noOfParanodeSets_collateral)]
        self.juxtaparanodes_collateral = [h.Section(name=f'juxtaparanodes_collateral[{loopCounter}]') for loopCounter in range(self.noOfJuxtaparanodeSets_collateral)]
        self.internodes_collateral = [h.Section(name=f'internodes_collateral[{loopCounter}]') for loopCounter in range(self.noOfInternodes_collateral)]


        # Defining topology of the myelinated collateral
        for loopCounter in range(self.noOfNodes_collateral - 1):
            self.paranodeOnes_collateral[2*loopCounter].connect(self.nodes_collateral[loopCounter](1))
            self.paranodeTwos_collateral[2*loopCounter].connect(self.paranodeOnes_collateral[2*loopCounter](1))
            self.paranodeThrees_collateral[2*loopCounter].connect(self.paranodeTwos_collateral[2*loopCounter](1))
            self.paranodeFours_collateral[2*loopCounter].connect(self.paranodeThrees_collateral[2*loopCounter](1))
            self.juxtaparanodes_collateral[2*loopCounter].connect(self.paranodeFours_collateral[2*loopCounter](1))
            self.internodes_collateral[loopCounter].connect(self.juxtaparanodes_collateral[2*loopCounter](1))
            self.juxtaparanodes_collateral[2*loopCounter+1].connect(self.internodes_collateral[loopCounter](1))
            self.paranodeFours_collateral[2*loopCounter+1].connect(self.juxtaparanodes_collateral[2*loopCounter+1](1))
            self.paranodeThrees_collateral[2*loopCounter+1].connect(self.paranodeFours_collateral[2*loopCounter+1](1))
            self.paranodeTwos_collateral[2*loopCounter+1].connect(self.paranodeThrees_collateral[2*loopCounter+1](1))
            self.paranodeOnes_collateral[2*loopCounter+1].connect(self.paranodeTwos_collateral[2*loopCounter+1](1))
            self.nodes_collateral[loopCounter+1].connect(self.paranodeOnes_collateral[2*loopCounter+1](1))
            
        # Creating section lists
        self.Nodes_collateral = h.SectionList()
        self.ParanodeOnes_collateral = h.SectionList()
        self.ParanodeTwos_collateral = h.SectionList()
        self.ParanodeThrees_collateral = h.SectionList()
        self.ParanodeFours_collateral = h.SectionList()
        self.Paranodes_collateral = h.SectionList()
        self.Juxtaparanodes_collateral = h.SectionList()
        self.Internodes_collateral = h.SectionList()
        self.TotalCollateral = h.SectionList()
        self.ExposedCollateral = h.SectionList()
        self.MyelinatedCollateral = h.SectionList()

        # Defining subsets within the myelinated collateral
        for loopCounter in range(self.noOfNodes_collateral):
            self.Nodes_collateral.append(self.nodes_collateral[loopCounter])
            self.TotalCollateral.append(self.nodes_collateral[loopCounter])
            self.ExposedCollateral.append(self.nodes_collateral[loopCounter])
            
        for loopCounter in range(self.noOfParanodeSets_collateral):
            self.ParanodeOnes_collateral.append(self.paranodeOnes_collateral[loopCounter])
            self.ParanodeTwos_collateral.append(self.paranodeTwos_collateral[loopCounter])
            self.ParanodeThrees_collateral.append(self.paranodeThrees_collateral[loopCounter])
            self.ParanodeFours_collateral.append(self.paranodeFours_collateral[loopCounter])
            self.Paranodes_collateral.append(self.paranodeOnes_collateral[loopCounter])
            self.Paranodes_collateral.append(self.paranodeTwos_collateral[loopCounter])
            self.Paranodes_collateral.append(self.paranodeThrees_collateral[loopCounter])
            self.Paranodes_collateral.append(self.paranodeFours_collateral[loopCounter])
            self.TotalCollateral.append(self.paranodeOnes_collateral[loopCounter])
            self.TotalCollateral.append(self.paranodeTwos_collateral[loopCounter])
            self.TotalCollateral.append(self.paranodeThrees_collateral[loopCounter])
            self.TotalCollateral.append(self.paranodeFours_collateral[loopCounter])
            self.MyelinatedCollateral.append(self.paranodeOnes_collateral[loopCounter])
            self.MyelinatedCollateral.append(self.paranodeTwos_collateral[loopCounter])
            self.MyelinatedCollateral.append(self.paranodeThrees_collateral[loopCounter])
            self.MyelinatedCollateral.append(self.paranodeFours_collateral[loopCounter])
            
        for loopCounter in range(self.noOfJuxtaparanodeSets_collateral):
            self.Juxtaparanodes_collateral.append(self.juxtaparanodes_collateral[loopCounter])
            self.TotalCollateral.append(self.juxtaparanodes_collateral[loopCounter])
            self.MyelinatedCollateral.append(self.juxtaparanodes_collateral[loopCounter])
            
        for loopCounter in range(self.noOfInternodes_collateral):
            self.Internodes_collateral.append(self.internodes_collateral[loopCounter])
            self.TotalCollateral.append(self.internodes_collateral[loopCounter])
            self.MyelinatedCollateral.append(self.internodes_collateral[loopCounter])