//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2016 Richard S. Smith and collaborators.
//
// If you use MorphoGraphX in your work, please cite:
//   http://dx.doi.org/10.7554/eLife.05864
//
// MorphoGraphX is free software, and is licensed under under the terms of the 
// GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
//

// Surface class
#ifndef DYNAMX_PROCESS_UNIFORM_GROWTH_HPP
#define DYNAMX_PROCESS_UNIFORM_GROWTH_HPP

#include <Process.hpp>

namespace mgx
{
  class mgxBase_EXPORT UniformGrowth : public Process 
  {
  public:
    UniformGrowth(const Process &process) : Process(process) {}

    // Initialize the surface
    bool initialize(QStringList &parms, QWidget *parent);

    // Run a step of the growth
    bool step(const QStringList &parms);

		// Rewind the surface
		bool rewind(QStringList &parms, QWidget *parent);

    // Process long description
    QString description() const { return "Uniform growth"; }

    // Parameters
		enum ParmNames { pDt, pDrawSteps, pXGrowth, pYGrowth, pZGrowth, pTissueParmsProc, pNumParms }; 

    QStringList parmNames() const 
    {
      QVector <QString> vec(pNumParms);

      vec[pDt] = "Dt";
      vec[pDrawSteps] = "DrawSteps";
      vec[pXGrowth] = "X Growth";
      vec[pYGrowth] = "Y Growth";
      vec[pZGrowth] = "Z Growth";
      vec[pTissueParmsProc] = "Tissue Parms Process";

			return vec.toList();
    }

    QStringList parmDescs() const 
    {
      QVector <QString> vec(pNumParms);

      vec[pDt] = "Growth timestep";
      vec[pDrawSteps] = "Steps between drawn frames";
      vec[pXGrowth] = "Growth in X direction";
      vec[pYGrowth] = "Growth in Y direction";
      vec[pZGrowth] = "Growth in Z direction";
      vec[pTissueParmsProc] = "Process to hold tissue parameters";
			
			return vec.toList();
    }

    QStringList parmDefaults() const 
    {
      QVector <QString> vec(pNumParms);

      vec[pDt] = "0.001";
      vec[pDrawSteps] = "1";
      vec[pXGrowth] = "2.0";
      vec[pYGrowth] = "1.0";
      vec[pZGrowth] = "0.0";
      vec[pTissueParmsProc] = "TissueParms";
      
			return vec.toList();
    }

    ParmChoiceMap parmChoice() const 
    {
      ParmChoiceMap map;
      return map;
    }

    // Plug-in icon
    QIcon icon() const { return QIcon(":/images/Closing.png"); }

  private:
    // Read parameters
		void processParms(const QStringList &parms);
        
		// Model parameters from GUI
    double dt;                 // Timestep
    int drawSteps;             // Steps per GUI update
    Point3d growthRate;        // Growth Rate

		// Mesh object
    Mesh *mesh;         // Current mesh
    CellTissue *T;      // Cellular tissue

    // Define all global data you want to save in the mesh in the attributes 
    double &time() 
    { 
      return mesh->attributes().attrMap<QString, double>("UniformGrowth Time")["Time"]; 
    }
  };

  /**
   * \class UniformInitialCell DynamXProcessUniformGrowth.hpp <DynamXProcessUniformGrowth.hpp>
   *
   * Process to create an initial cell.
   *
   * \ingroup GrowingSurfaceProcesses
   */
  class mgxBase_EXPORT UniformInitialCell : public Process 
  {
  public:
    UniformInitialCell(const Process &process) : Process(process) {}

    /// Make the initial cell
    bool run(const QStringList &parms)
    {
      Mesh *mesh = currentMesh();
      if(not mesh)
        throw(QString("No current mesh"));
      return run(mesh, parms[0].toDouble(), parms[1].toInt());
    }
    bool run(Mesh* mesh, double size, int walls);

    // Functions for Gui
    QString description() const { return "Create an initial cell."; }
    QStringList parmNames() const { return QStringList() << "Size" << "Walls"; }
    QStringList parmDescs() const { return QStringList() 
                                    << "Size of the cell" << "Number of walls"; }
    QStringList parmDefaults() const { return QStringList() << "5.0" << "7"; }

    // Icon file
    QIcon icon() const { return QIcon(":/images/InitialCell.png"); }
  };
}  
#endif
