'''
Neuron simulator export for:

Components:
    null (Type: notes)
    BK_IAMC_ChannelML (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    null (Type: notes)
    CaV_R_iAMC_ChannelML (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    null (Type: notes)
    Gran_CaPool_98 (Type: decayingPoolConcentrationModel:  restingConc=7.55E-5 (SI concentration) decayConstant=0.01 (SI time) shellThickness=8.4E-8 (SI length) Faraday=96485.3 (SI charge_per_mole) AREA_SCALE=1.0 (SI area) LENGTH_SCALE=1.0 (SI length))
    null (Type: notes)
    KA_iAMC_ChannelML (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    null (Type: notes)
    Kdr_iAMC_ChannelML (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    null (Type: notes)
    LeakConductance (Type: ionChannelPassive:  conductance=1.0E-11 (SI conductance))
    null (Type: notes)
    NaP_iAMC_ChannelML (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    null (Type: notes)
    NaxSH0_ChannelML (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    null (Type: notes)
    NaxSH10_ChannelML (Type: ionChannelHH:  conductance=1.0E-11 (SI conductance))
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    iMC1_cell_1_origin (Type: cell)
    null (Type: notes)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    null (Type: include)
    network_AOB_MC_neuroConstruct (Type: networkWithTemperature:  temperature=308.15 (SI temperature))
    sim1 (Type: Simulation:  length=2.0 (SI time) step=1.0E-5 (SI time))


    This NEURON file has been generated by org.neuroml.export (see https://github.com/NeuroML/org.neuroml.export)
         org.neuroml.export  v1.5.0
         org.neuroml.model   v1.5.0
         jLEMS               v0.9.8.7

'''

import neuron

import time
h = neuron.h
h.load_file("nrngui.hoc")

h("objref p")
h("p = new PythonObject()")

class NeuronSimulation():

    def __init__(self, tstop, dt):

        print("\n    Starting simulation in NEURON generated from NeuroML2 model...\n")

        # Adding simulation Component(id=sim1 type=Simulation) of network/component: network_AOB_MC_neuroConstruct (Type: networkWithTemperature:  temperature=308.15 (SI temperature))

        # Temperature used for network: 308.15 K
        h.celsius = 308.15 - 273.15

        print("Population CellGroup_0 contains 1 instance(s) of component: iMC1_cell_1_origin of type: cell")

        print("Setting the default initial concentrations for ca (used in iMC1_cell_1_origin) to 7.55E-5 mM (internal), 2.4 mM (external)")
        h("cai0_ca_ion = 7.55E-5")
        h("cao0_ca_ion = 2.4")

        print("Setting the default initial concentrations for ca (used in iMC1_cell_1_origin) to 7.55E-5 mM (internal), 2.4 mM (external)")
        h("cai0_ca_ion = 7.55E-5")
        h("cao0_ca_ion = 2.4")

        h.load_file("iMC1_cell_1_origin.hoc")
        a_CellGroup_0 = []
        h("{ n_CellGroup_0 = 1 }")
        h("objectvar a_CellGroup_0[n_CellGroup_0]")
        for i in range(int(h.n_CellGroup_0)):
            h("a_CellGroup_0[%i] = new iMC1_cell_1_origin()"%i)
            h("access a_CellGroup_0[%i].filament_100000001_0"%i)

        h("{ a_CellGroup_0[0].position(84.929596, 16.823599, 21.396654) }")

        h("proc initialiseV_CellGroup_0() { for i = 0, n_CellGroup_0-1 { a_CellGroup_0[i].set_initial_v() } }")
        h("objref fih_CellGroup_0")
        h('{fih_CellGroup_0 = new FInitializeHandler(0, "initialiseV_CellGroup_0()")}')

        h("proc initialiseIons_CellGroup_0() { for i = 0, n_CellGroup_0-1 { a_CellGroup_0[i].set_initial_ion_properties() } }")
        h("objref fih_ion_CellGroup_0")
        h('{fih_ion_CellGroup_0 = new FInitializeHandler(1, "initialiseIons_CellGroup_0()")}')

        trec = h.Vector()
        trec.record(h._ref_t)

        h.tstop = tstop

        h.dt = dt

        h.steps_per_ms = 1/h.dt

        # Display: self.display_CellGroup_0_v
        self.display_CellGroup_0_v = h.Graph(0)
        self.display_CellGroup_0_v.size(0,h.tstop,-80.0,50.0)
        self.display_CellGroup_0_v.view(0, -80.0, h.tstop, 130.0, 80, 330, 330, 250)
        h.graphList[0].append(self.display_CellGroup_0_v)
        # Line, plotting: CellGroup_0/0/iMC1_cell_1_origin/0/v
        self.display_CellGroup_0_v.addexpr("a_CellGroup_0[0].filament_100000001_0.v(0.040173028)", "a_CellGroup_0[0].filament_100000001_0.v(0.040173028)", 1, 1, 0.8, 0.9, 2)



        # File to save: CellGroup_0_v_0_0_OF
        # Column: CellGroup_0/0/iMC1_cell_1_origin/0/v
        h(' objectvar v_v_CellGroup_0_v_0_0_OF ')
        h(' { v_v_CellGroup_0_v_0_0_OF = new Vector() } ')
        h(' { v_v_CellGroup_0_v_0_0_OF.record(&a_CellGroup_0[0].filament_100000001_0.v(0.040173028)) } ')
        h.v_v_CellGroup_0_v_0_0_OF.resize((h.tstop * h.steps_per_ms) + 1)

        # File to save: time
        # Column: time
        h(' objectvar v_time ')
        h(' { v_time = new Vector() } ')
        h(' { v_time.record(&t) } ')
        h.v_time.resize((h.tstop * h.steps_per_ms) + 1)

        self.initialized = False

        self.sim_end = -1 # will be overwritten

        h.nrncontrolmenu()


    def run(self):

        self.initialized = True
        sim_start = time.time()
        print("Running a simulation of %sms (dt = %sms)" % (h.tstop, h.dt))

        h.run()

        self.sim_end = time.time()
        sim_time = self.sim_end - sim_start
        print("Finished NEURON simulation in %f seconds (%f mins)..."%(sim_time, sim_time/60.0))

        self.save_results()


    def advance(self):

        if not self.initialized:
            h.finitialize()
            self.initialized = True

        h.fadvance()


    def save_results(self):

        print("Saving results at t=%s..."%h.t)

        if self.sim_end < 0: self.sim_end = time.time()

        self.display_CellGroup_0_v.exec_menu("View = plot")

        # File to save: time
        py_v_time = [ t/1000 for t in h.v_time.to_python() ]  # Convert to Python list for speed...

        f_time_f2 = open('/home/Simon/NML2_Test/iAMC_Fig10H2T/AOB_MC_neuroConstruct/simulations/Sim_11/time.dat', 'w')
        num_points = len(py_v_time)  # Simulation may have been stopped before tstop...

        for i in range(num_points):
            f_time_f2.write('%f'% py_v_time[i])  # Save in SI units...+ '\n')
        f_time_f2.close()
        print("Saved data to: /home/Simon/NML2_Test/iAMC_Fig10H2T/AOB_MC_neuroConstruct/simulations/Sim_11/time.dat")

        # File to save: CellGroup_0_v_0_0_OF
        py_v_v_CellGroup_0_v_0_0_OF = [ float(x  / 1000.0) for x in h.v_v_CellGroup_0_v_0_0_OF.to_python() ]  # Convert to Python list for speed, variable has dim: voltage

        f_CellGroup_0_v_0_0_OF_f2 = open('/home/Simon/NML2_Test/iAMC_Fig10H2T/AOB_MC_neuroConstruct/simulations/Sim_11/CellGroup_0_0.0.dat', 'w')
        num_points = len(py_v_time)  # Simulation may have been stopped before tstop...

        for i in range(num_points):
            f_CellGroup_0_v_0_0_OF_f2.write('%e\t'% py_v_time[i]  + '%e\t'%(py_v_v_CellGroup_0_v_0_0_OF[i]) + '\n')
        f_CellGroup_0_v_0_0_OF_f2.close()
        print("Saved data to: /home/Simon/NML2_Test/iAMC_Fig10H2T/AOB_MC_neuroConstruct/simulations/Sim_11/CellGroup_0_0.0.dat")

        save_end = time.time()
        save_time = save_end - self.sim_end
        print("Finished saving results in %f seconds"%(save_time))

        print("Done")

if __name__ == '__main__':

    ns = NeuronSimulation(tstop=2000.0, dt=0.01)

    ns.run()

