/*
 *       File name:  libcn/standalone-neurons.cc
 *         Project:  cnrun
 *          Author:  Andrei Zavada <johnhommer@gmail.com>
 *                   building on original work by Thomas Nowotny <tnowotny@ucsd.edu>
 * Initial version:  2008-08-02
 *
 *         Purpose:  standalone neurons (those not having state vars
 *                   on model's integration vector)
 *
 *         License:  GPL-2+
 */

#ifndef CNRUN_LIBCN_STANDALONENEURONS_H_
#define CNRUN_LIBCN_STANDALONENEURONS_H_

#if HAVE_CONFIG_H && !defined(VERSION)
#  include "config.h"
#endif

#include "libstilton/lang.hh"
#include "forward-decls.hh"
#include "base-neuron.hh"
#include "standalone-attr.hh"
#include "mx-attr.hh"


namespace cnrun {

class C_StandaloneNeuron
  : public C_BaseNeuron, public C_StandaloneAttributes {

        DELETE_DEFAULT_METHODS (C_StandaloneNeuron)

    protected:
        C_StandaloneNeuron (TUnitType intype, const string& inlabel,
                            double x, double y, double z,
                            CModel*, int s_mask);

    public:
        double &var_value( size_t v)                  {  return V[v];  }
        const double &get_var_value( size_t v) const  {  return V[v];  }
        void reset_vars()
                {
                        memcpy( V.data(), __CNUDT[_type].stock_var_values,
                                sizeof(double) * v_no());
                        memcpy( V_next.data(), __CNUDT[_type].stock_var_values,
                                sizeof(double) * v_no());
                }
};



class C_StandaloneConductanceBasedNeuron
  : public C_StandaloneNeuron {

        DELETE_DEFAULT_METHODS (C_StandaloneConductanceBasedNeuron)

    protected:
        C_StandaloneConductanceBasedNeuron (TUnitType intype, const string& inlabel,
                                            double inx, double iny, double inz,
                                            CModel *inM, int s_mask)
              : C_StandaloneNeuron (intype, inlabel, inx, iny, inz, inM, s_mask)
                {}

    public:
        double E() const                        {  return V[0];  }
        double E( vector<double>&) const        {  return V[0];  }

        size_t n_spikes_in_last_dt() const;
};


class C_StandaloneRateBasedNeuron
  : public C_StandaloneNeuron {

        DELETE_DEFAULT_METHODS (C_StandaloneRateBasedNeuron)

    protected:
        C_StandaloneRateBasedNeuron (TUnitType intype, const string& inlabel,
                                     double inx, double iny, double inz,
                                     CModel *inM, int s_mask)
              : C_StandaloneNeuron (intype, inlabel, inx, iny, inz, inM, s_mask)
                {}

    public:
        size_t n_spikes_in_last_dt() const;
};








class CNeuronHH_r
  : public C_StandaloneRateBasedNeuron {

        DELETE_DEFAULT_METHODS (CNeuronHH_r)

    public:
        CNeuronHH_r( const string& inlabel,
                     double x, double y, double z,
                     CModel *inM, int s_mask = 0)
              : C_StandaloneRateBasedNeuron( NT_HH_R, inlabel, x, y, z, inM, s_mask)
                {}

        enum {
                _a_, _I0_, _r_, _Idc_,
        };

        double F( vector<double>&) const  __attribute__ ((hot));

        void preadvance() __attribute__ ((hot));
};








class COscillatorPoisson
  : public C_StandaloneConductanceBasedNeuron {

        DELETE_DEFAULT_METHODS (COscillatorPoisson)

    public:
        COscillatorPoisson( const string& inlabel,
                            double x, double y, double z,
                            CModel *inM, int s_mask = 0)
              : C_StandaloneConductanceBasedNeuron (NT_POISSON, inlabel, x, y, z, inM, s_mask)
                {
                      // need _spikelogger_agent's fields even when no spikelogging is done
                        _spikelogger_agent = new SSpikeloggerService(
                                static_cast<C_BaseNeuron*>(this),
                                0 | CN_KL_PERSIST | CN_KL_IDLE);
                }

        enum {
                _lambda_, _trel_, _trelrfr_, _Vrst_, _Vfir_,
        };

        void possibly_fire() __attribute__ ((hot));

        void do_detect_spike_or_whatever() __attribute__ ((hot));
};










class COscillatorDotPoisson
  : public C_StandaloneConductanceBasedNeuron {

        DELETE_DEFAULT_METHODS (COscillatorDotPoisson)

    public:
        COscillatorDotPoisson (const string& inlabel,
                               double x, double y, double z,
                               CModel *inM, int s_mask = 0)
              : C_StandaloneConductanceBasedNeuron( NT_DOTPOISSON, inlabel, x, y, z, inM, s_mask)
                {
                      // need _spikelogger_agent's fields even when no spikelogging is done
                        _spikelogger_agent = new SSpikeloggerService(
                                static_cast<C_BaseNeuron*>(this),
                                0 | CN_KL_PERSIST | CN_KL_IDLE);
                }

        enum {
                _lambda_, _Vrst_, _Vfir_,
        };

        void do_detect_spike_or_whatever() __attribute__ ((hot));

        void possibly_fire() __attribute__ ((hot));

        unsigned n_spikes_in_last_dt()
                {  return V[1];  }

        double &nspikes()
                {  return V[1];  }
};



class CNeuronDotPulse
  : public C_StandaloneConductanceBasedNeuron {

        DELETE_DEFAULT_METHODS (CNeuronDotPulse)

    public:
        CNeuronDotPulse (const string& inlabel,
                         double x, double y, double z,
                         CModel *inM, int s_mask = 0)
              : C_StandaloneConductanceBasedNeuron (NT_DOTPULSE, inlabel, x, y, z, inM, s_mask)
                {}

        enum { _f_, _Vrst_, _Vfir_ };

        double &spikes_fired_in_last_dt()
                {  return V[1];  }

        void possibly_fire();

        void param_changed_hook();
};









class CNeuronMap
  : public C_StandaloneConductanceBasedNeuron {

        DELETE_DEFAULT_METHODS (CNeuronMap)

    public:
        static const constexpr double fixed_dt = 0.1;

        CNeuronMap (const string& inlabel, double x, double y, double z,
                    CModel*, int s_mask = 0);

        enum {
                _Vspike_, _alpha_, _gamma_, _beta_, _Idc_
        };

        void preadvance();
        void fixate();
    private:
        double _E_prev;

};

}

#endif

// Local Variables:
// Mode: c++
// indent-tabs-mode: nil
// tab-width: 8
// c-basic-offset: 8
// End:
