/*************************************************************************
 *    CompuCell - A software framework for multimodel simulations of     *
 * biocomplexity problems Copyright (C) 2003 University of Notre Dame,   *
 *                             Indiana                                   *
 *                                                                       *
 * This program is free software; IF YOU AGREE TO CITE USE OF CompuCell  *
 *  IN ALL RELATED RESEARCH PUBLICATIONS according to the terms of the   *
 *  CompuCell GNU General Public License RIDER you can redistribute it   *
 * and/or modify it under the terms of the GNU General Public License as *
 *  published by the Free Software Foundation; either version 2 of the   *
 *         License, or (at your option) any later version.               *
 *                                                                       *
 * This program is distributed in the hope that it will be useful, but   *
 *      WITHOUT ANY WARRANTY; without even the implied warranty of       *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    *
 *             General Public License for more details.                  *
 *                                                                       *
 *  You should have received a copy of the GNU General Public License    *
 *     along with this program; if not, write to the Free Software       *
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.        *
 *************************************************************************/

#ifndef CONTACTENERGY_H
#define CONTACTENERGY_H

#include <CompuCell3D/Potts3D/EnergyFunction.h>

#include <XMLCereal/XMLSerializable.h>


#include <CompuCell3D/Potts3D/Cell.h>
#include <BasicUtils/BasicClassAccessor.h>
#include <BasicUtils/BasicClassGroup.h> //had to include it to avoid problems with template instantiation

#include <map>
#include <vector>

namespace CompuCell3D {
  class Potts3D;
  class Automaton;
  
  class ContactEnergy : public EnergyFunction, public XMLSerializable {
    Potts3D *potts;

    typedef std::map<int, double> contactEnergies_t;
    typedef std::vector<std::vector<double> > contactEnergyArray_t;
    
    contactEnergies_t contactEnergies;

    contactEnergyArray_t contactEnergyArray;
    
    std::string autoName;
    double depth;

    Automaton *automaton;
    
  public:
    ContactEnergy(Potts3D *potts) :
            potts(potts), depth(1) {}
    
    virtual ~ContactEnergy() {}

    virtual double localEnergy(const Point3D &pt);
//      virtual double changeEnergy(const Point3D &pt, const Cell *newCell,
//                                  const Cell *oldCell);

    virtual double changeEnergy(const Point3D &pt, const CellG *newCell,
                                const CellG *oldCell);
    
				
    /**
     * @return The contact energy between cell1 and cell2.
     */
    double contactEnergy(const CellG *cell1, const CellG *cell2);

    /**
     * Sets the contact energy for two cell types.  A -1 type is interpreted
     * as the medium.
     */
    void setContactEnergy(const std::string typeName1,
			  const std::string typeName2, const double energy);


    // Begin XMLSerializable interface
    virtual void readXML(XMLPullParser &in);
    virtual void writeXML(XMLSerializer &out);
    // End XMLSerializable interface


  protected:
    /**
     * @return The index used for ordering contact energies in the map.
     */
    int getIndex(const int type1, const int type2) const;
  };
};
#endif
