//#ifdef NEURON_H
//#define NEURON_H
//#include <omp.h>
#include <unordered_map>
#include <string>
#include "cellVariables.h"
#include "cellParameters.h"
using namespace std;
class Neuron : public cellVariables, public cellParameters
{
public:
typedef unordered_map<string, double> Fmap;
typedef double (**FuncPtr)(cellVariables&, cellParameters&);
typedef double (*DFuncPtr)(cellVariables&, cellParameters&);
Neuron(); // default constructor
Neuron(string type_neuron,string type_synapse, string i_or_e, Fmap cell_vars, Fmap cell_pars); // constructor
Neuron(const Neuron& right_side); // copy costructor
~Neuron(); // destructor
Neuron& operator=(const Neuron& right_side); // assignment operator
void get_all_derivatives(double* synaptic_matrix_row, int number_of_neurons, Neuron* other_neurons); // getting the derivative numbers into the appropriate spaces
void get_all_derivatives(double si, double syn_strength); // getting the derivative numbers into the appropriate spaces
void get_all_derivatives(double* synaptic_matrix_row, int number_of_neurons, Neuron* other_neurons, double* sv); // externally supplied synaptic variables (for MPI)
void get_all_derivatives(double* synaptic_matrix_row, int number_of_neurons, Neuron* other_neurons, double* sv, int* valid_entries, int); //ditto + prepped synapse for efficient looping
void get_all_derivatives(double* synaptic_matrix_row, int number_of_neurons, double* prepped_esyn_array, double* sv, int* valid_entries, int); //ditto + prepped synapse AND esyn for efficient looping
void get_all_derivatives(double* synaptic_sorted_row, int* synaptic_location, int synaptic_size, double* prepped_esyn_array, double* sv); //ditto + even more prepping
void integrate_neuron(const double&, const double&, long*, int*, float*, int*, float*, long*, long*, long*, long*, long*, long*, int&, int&, int&, int&);
void integrate_neuron(const double&, const double&, long*, int*, float*, int*, float*, long*, long*, long*, long*, long*, long*, int&, int&, int&, int&, const int&);// for openmp threads
void integrate_neuron(const double&, const double&, long*); // integrates the neuron and put the results into appropriate temporary spaces
void integrate_neuron(const double&, const double&, long*, const int&); // for open mp threads
void integrate_synapse(const double&, const double&, long*, int*, float*, int*, float*, long*, long*, long*, long*, long*, long*, int&, int&, int&, int&);
void integrate_synapse(const double&, const double&, long*, int*, float*, int*, float*, long*, long*, long*, long*, long*, long*, int&, int&, int&, int&, const int&);// for open mp
void integrate_synapse(const double&, const double&, long*); // integrates the synapse and put the results into appropriate temporary spaces
void integrate_synapse(const double&, const double&, long*, const int&);// for open mp threads
void update_synapse(); // updates a particular neuron's associated synapse information into cellVariables
void update_neuron(); // updates a particular neuron's information into cellVariables
void update(); // wrapper function for update_synapse and update neuron
double display_current_balance_derivative(int); // Added October 22nd, 2010.
string display_type();
int* find_valid_synapse_entries(double* synapse_matrix_row, int number_of_neurons, int&); //synapse prepping routine for efficient looping
double prep_synapse_reversal_potential(); //same as above
int spiked; // flag to tell whether a neuron has just spiked (applies only to discontinuous synapses)
private:
FuncPtr current_balance_equations; //pointer to array of functions (current balance)
FuncPtr synapse_equations; //pointer to array of functions (synapse)
double* current_balance_readings; // store temp integrated results
double* synapse_readings;
double* current_balance_derivatives; // store derivatives for integration
double* synapse_derivatives;
double* synapse_array; // array to store delayed synapse variables
double* synapse_array_current_position; // pointer that points to the current position of the synapse array
string type_of_neuron;
string type_of_synapse;
string inh_or_exc;
int number_of_current_balance_equations;
int number_of_synapse_equations;
int synapse_array_length; // size of synapse array
//Flags
int got_current_balance_equations;
int got_synapse_equations;
int got_space_current_balance_results;
int got_space_synapse_results;
int update_neuron_happened;
int synapse_array_assigned;
void get_current_balance_equations();
void get_space_current_balance_results();
void get_synapse_equations();
void get_space_synapse_results();
void get_current_balance_derivatives_no_psps();
void check_and_get_spaces_all_derivatives();
void assign_all_derivatives_to_neuron(double summed_psps);
void assign_synapse_array();
double get_summed_psps(double* synaptic_matrix_row, int number_of_neurons, Neuron* other_neurons);
double get_summed_psps(double* synaptic_matrix_row, int number_of_neurons, Neuron* othre_neurons, double* delayed_synapse_array);
double get_summed_psps(double* synaptic_matrix_row, int number_of_neurons, Neuron* other_neurons, double* delayed_synapse_array, int* valid_entries, int number_of_entries);
double get_summed_psps(double* synaptic_matrix_row, int number_of_neurons, double* array_of_esyn, double* delayed_synapse_array, int* valid_entries, int number_of_entries);
double get_summed_psps(double* synaptic_sorted_row, int* synaptic_location, int synaptic_size, double* array_of_esyn, double* delayed_synapse_array);
double compute_one_psp(const double& si, Neuron* other_neuron);
double compute_one_psp(const double& si, const double& esyn);
double compute_one_psp(const Neuron& other_neuron);
double compute_one_psp(double, string);
void get_synapse_derivatives();
void copy_current_synapse_wrapper(const Neuron& right_side);
void copy_synapse_equations(const Neuron& right_side);
void copy_current_equations(const Neuron& right_side);
void copy_space_current_balance_results(const Neuron& right_side);
void copy_space_synapse_results(const Neuron& right_side);
void copy_synapse_array(const Neuron& right_side);
void synapse_push();
};
//#endif