/**********************************************************************
** This program is part of 'MOOSE', the
** Messaging Object Oriented Simulation Environment.
**           Copyright (C) 2003-2009 Upinder S. Bhalla. and NCBS
** It is made available under the terms of the
** GNU Lesser General Public License version 2.1
** See the file COPYING.LIB for the full notice.
**********************************************************************/

#ifndef _NEUTRAL_H
#define _NEUTRAL_H


class Neutral
{
public:
    friend istream& operator>>(istream& s, Neutral& d);
    friend ostream& operator<<(ostream& s, const Neutral& d);
    Neutral();

    /////////////////////////////////////////////////////////////////
    // Field access functions
    /////////////////////////////////////////////////////////////////

    /**
     * Field access functions for the entire object. For Neutrals
     * the setThis function is a dummy: it doesn't do anything because
     * the Neutral has no data to set. However, the function name acts
     * as a placeholder and derived objects can override the function
     * so that the entire object can be accessed as a field and also
     * for inter-node data transfer.
     */
    void setThis(Neutral v);

    /**
     * Field access functions for the entire object. For Neutrals
     * the getThis function does return the Neutral object, but it
     * has no data to set. However, the function name acts
     * as a placeholder and derived objects can override the function
     * so that the entire object can be accessed as a field and also
     * used for inter-node data transfer.
     */
    Neutral getThis() const;

    /**
     * Field access functions for the name of the Element/Neutral
     */
    void setName(const Eref& e, string name);
    string getName(const Eref& e) const;

    /**
     * Readonly field access function for getting all outgoing Msgs.
     */
    vector<ObjId> getOutgoingMsgs(const Eref& e) const;

    /**
     * Readonly field access function for getting all incoming Msgs.
     */
    vector<ObjId> getIncomingMsgs(const Eref& e) const;

    /**
     * Readonly field access function for getting Ids connected to
     * current Id via specified Field.
     * Field is specified by its name.
     * Returns an empty vector if it fails.
     */
    vector<Id> getNeighbors(const Eref& e, string field) const;

    /**
     * Return vector of target ObjIds
     * called by the specified SrcFinfo, by the current object.
     * Twin function to getMsgDestFunctions.
     */
    vector<ObjId> getMsgDests(const Eref& e, string src) const;

    /**
     * Return vector of function names called on each target ObjId
     * of the specified SrcFinfo, by the current object.
     * Twin function to getMsgDests.
     */
    vector<string> getMsgDestFunctions(const Eref& e, string src) const;

    /**
     * Returns True if the object is derived from the specified class
     */
    bool isA(const Eref& e, string className) const;

    /**
     * Simply returns own ObjId
     */
    ObjId getObjId(const Eref& e) const;

    /**
     * Looks up the full Id info for the parent of the current Element
     */
    ObjId getParent(const Eref& e) const;

    /**
     * Looks up all the Element children of the current Element
     */
    vector<Id> getChildren(const Eref& e) const;

    /**
     * Builds a vector of all descendants of e
     */
    unsigned int buildTree(const Eref& e, vector<Id>& tree) const;

    /**
     * Traverses to root, building path.
     */
    string getPath(const Eref& e) const;

    /**
     * Looks up the Class name of the current Element
     */
    string getClass(const Eref& e) const;

    /**
     * numData is the number of data entries on this Element.
     */
    void setNumData(const Eref& e, unsigned int num);
    unsigned int getNumData(const Eref& e) const;

    /**
     * numField is the size of the field array on the FieldElement
     * specified by the Eref including its data index.
     */
    void setNumField(const Eref& e, unsigned int num);
    unsigned int getNumField(const Eref& e) const;

    /// Id is the Id of the object, converted to unsigned int.
    unsigned int getId(const Eref& e) const;

    /// Index is the dataIndex of the object
    unsigned int getIndex(const Eref& e) const;

    /// fieldIndex specifies field entry if FieldElement. Otherwise zero
    unsigned int getFieldIndex(const Eref& e) const;

    /**
     * The clock Tick specifies the timing and order of execution
     * of the 'process' action of this object in the simulation.
     * The timing is set by assigning the appropriate dt to
     * this tick in the Clock object.
     * A value of -1 means that the object is disabled.
     */
    void setTick(const Eref& e, int num);

    /// Returns clock tick of this object.
    int getTick(const Eref& e) const;

    /// Returns dt associated with this object based on its clock tick.
    double getDt(const Eref& e) const;

    /// Information function to return names of all value Finfos.
    vector<string> getValueFields(const Eref& e) const;

    /// Information function to return names of all SrcFinfos.
    vector<string> getSourceFields(const Eref& e) const;

    /// Information function to return names of all DestFinfos.
    vector<string> getDestFields(const Eref& e) const;
    ////////////////////////////////////////////////////////////
    // DestFinfo functions
    ////////////////////////////////////////////////////////////

    /**
     * Destroys Element and all children
     */
    void destroy(const Eref& e, int stage);

    /**
     * Request conversion of data into a blockDataHandler subclass,
     * and to carry out node balancing of data as per args.
     */
    void blockNodeBalance(const Eref& e, unsigned int, unsigned int,
                          unsigned int);

    /**
     * Request conversion of data into a generalDataHandler subclass,
     * and to carry out node balancing of data as per args.
     */
    void generalNodeBalance(const Eref& e, unsigned int myNode,
                            vector<unsigned int> nodeAssignment);

    ////////////////////////////////////////////////////////////
    // Static utility functions
    ////////////////////////////////////////////////////////////

    /**
     * Finds specific named child
     */
    static Id child(const Eref& e, const string& name);

    /**
     * Returns parent object
     */
    static ObjId parent(const Eref& e);
    static ObjId parent(ObjId id);

    /**
     * Checks if 'me' is a descendant of 'ancestor'
     */
    static bool isDescendant(Id me, Id ancestor);

    /**
     * Standard initialization function, used whenever we want to
     * look up the class Cinfo
     */
    static const Cinfo* initCinfo();

    /**
     * return ids of all the children in ret.
     */
    static void children(const Eref& e, vector<Id>& ret);

    /**
     * Finds the path of element e
     */
    static string path(const Eref& e);

    /**
     * Checks if specified field is a global, typically because it is
     * present on the Element and therefore should be assigned uniformly
     * on all nodes
     */
    static bool isGlobalField(const string& field);

private:
    // string name_;
};

#endif  // _NEUTRAL_H
