//
// 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.
//

#ifndef DYNAMX_PROCESS_CELL_DIVIDE_HPP
#define DYNAMX_PROCESS_CELL_DIVIDE_HPP

/**
 * \file DynamXProcessCellDivide.hpp
 *
 * This file contains the process to divide Tissue cells.  
 */

#include <Process.hpp>
#include <CellTissue.hpp>
#include <MGXSubdivide.hpp>

namespace mgx
{
  // Process to perform cell division in a 2D Tissue Mesh (MGX2D)
  class mgxBase_EXPORT CellDivide : public Process 
  {
  public:
    CellDivide(const Process &process) : Process(process) {}

    ~CellDivide() {}

    // Initialize simulation, called from GUI thread
    bool initialize(QStringList &parms, QWidget* parent);
  
    // Run a step of cell division
    bool step(const QStringList &parms) 
    { 
      Mesh *mesh = currentMesh();
      MGXSubdivide sDiv(mesh);
      return step(mesh, &sDiv);
    }

    // Run a step of cell division
    virtual bool step(Mesh *mesh, Subdivide *sDiv);

    // Cannot rewind subdivision, do nothing
    bool rewind(QStringList &parms, QWidget *parent) { return true; }

    // Functions for Gui
    QString description() const { return "Parameters for cell division on tissue mesh."; }

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

      vec[CellDivideMgx2d::pCellMaxArea] = "CellMaxArea";
      vec[CellDivideMgx2d::pCellDivAlg] = "CellDivAlg";
      vec[CellDivideMgx2d::pCellWallSample] = "CellWallSample";
      vec[CellDivideMgx2d::pCellPinch] = "CellPinch";
      vec[CellDivideMgx2d::pCellMaxPinch] = "CellMaxPinch";
      vec[CellDivideMgx2d::pCellWallMin] = "CellWallMin";

      return vec.toList();
    }
    QStringList parmDescs() const 
    {
      QVector <QString> vec(CellDivideMgx2d::pNumParms);

      vec[CellDivideMgx2d::pCellMaxArea] = "Area threshold for cell division";
      vec[CellDivideMgx2d::pCellDivAlg] = "Division Algorithm";
      vec[CellDivideMgx2d::pCellWallSample] = "Cell wall sample size";
      vec[CellDivideMgx2d::pCellPinch] = "Amount to pinch walls";
      vec[CellDivideMgx2d::pCellMaxPinch] = "Max amount to pinch walls";
      vec[CellDivideMgx2d::pCellWallMin] = "Min dist during division to existing vertex";

      return vec.toList();
    }
    QStringList parmDefaults() const 
    {
      QVector <QString> vec(CellDivideMgx2d::pNumParms);

      vec[CellDivideMgx2d::pCellMaxArea] = "25";
      vec[CellDivideMgx2d::pCellDivAlg] = "Shortest Wall";
      vec[CellDivideMgx2d::pCellWallSample] = "0.05";
      vec[CellDivideMgx2d::pCellPinch] = "0.2";
      vec[CellDivideMgx2d::pCellMaxPinch] = "1";
      vec[CellDivideMgx2d::pCellWallMin] = "0.03";

      return vec.toList();
    }

    ParmChoiceMap parmChoice() const
    {
      ParmChoiceMap map;
      map[1] = QStringList() << "Shortest Wall" << "Closest Midpoint"
                             << "Closest Wall" << "Shortest Direction";
      return map;
    }

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

    private: 
      Mesh *mesh;
      CellTissue *T;
  };
}

#endif

