//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2015 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 __BEZIERPROCESS_HPP__
#define __BEZIERPROCESS_HPP__

#include <Process.hpp>
#include <Parms.hpp>
#include <Bezier.hpp>

// I had to make a file separate from Bezier, because Bezier.hpp is included in CuttingSurface.hpp, which itself is included into Process.hpp

namespace mgx {

  /**
   * \class LoadBezier <BezierProcess.hpp>
   */
  class mgxBase_EXPORT LoadBezier : public Process {
  public:
    LoadBezier(const Process& process) : Process(process)
    {
      setName("Misc/Bezier/Load Bezier");
      setDesc("Load Bezier from a parameter file.");
      setIcon(QIcon(":/images/open.png"));

      addParm("Input File","Path to input file. If empty, a browser will open.",""); // 0
    }

    bool initialize(QWidget* parent);

    bool run()
    {
      return run(parm("Input File"));
    }

    bool run(const QString& filename);
  };

  /**
   * \class SaveBezier <BezierProcess.hpp>
   */
  class mgxBase_EXPORT SaveBezier : public Process {
  public:
    SaveBezier(const Process& process) : Process(process)
    {
      setName("Misc/Bezier/Save Bezier");
      setDesc("Save Bezier to a parameter file.");
      setIcon(QIcon(":/images/save.png"));

      addParm("Output File","Path to output file. If empty, a browser will open.",""); // 0
    }

    bool initialize(QWidget* parent);

    bool run()
    {
      return run(parm("Output File"));
    }

    bool run(const QString& filename);

  };


	 /**
   * \class NewBezier <BezierProcess.hpp>
   */
  class mgxBase_EXPORT NewBezier : public Process {
  public:
    NewBezier(const Process& process) : Process(process)
    {
      setName("Misc/Bezier/New Bezier");
      setDesc("New Bezier from parameters.");
      setIcon(QIcon(":/images/Bezier.png"));

      addParm("Controls X","Nb of control points in X","5"); // 0
      addParm("Controls Y","Nb of control points in Y","5"); // 1
      addParm("Size X","Physical size along X (um)","200"); // 2
      addParm("Size Y","Physical size along Y (um)","200"); // 3
      addParm("Lines in X","Nb of lines to draw in X","15"); // 4
      addParm("Lines in Y","Nb of lines to draw in Y","15"); // 5
    }

    bool initialize(QWidget* parent) { return true; }

    bool run() {
      return run(parm("Controls X").toInt(), parm("Controls Y").toInt(), parm("Size X").toFloat(),
        parm("Size Y").toFloat(), parm("Lines in X").toInt(), parm("Lines in Y").toInt());
    }

    bool run(uint bezPointsX, uint bezPointsY, float sizeX, float sizeY, uint linesX, uint linesY);
  };


class mgxBase_EXPORT MeasureBezier : public Process
  {
  public:
    MeasureBezier(const Process& process) : Process(process)
    {
      setName("Misc/Bezier/Measure/Simple Measure");
      setDesc("Measures the area of the Bezier grid and the length of the Bezier line at point v=0");
      setIcon(QIcon(":/images/MakeHeatMap.png"));

      addParm("Discretization Points","Number of discretization points","200"); // 0
    }

    bool run()
    {
      Mesh* m = currentMesh();
      return run(m, parm("Discretization Points").toInt());
    }
    bool run(Mesh* m, int discretization);
  };


class mgxBase_EXPORT MeasureBezierExport : public Process
  {
  public:
    MeasureBezierExport(const Process& process) : Process(process)
    {
      setName("Misc/Bezier/Measure/Export Measure");
      setDesc("Measures the area of the Bezier grid and the length of the Bezier line at point v=0");
      setIcon(QIcon(":/images/MakeHeatMap.png"));

      addParm("Discretization Points","Number of discretization points","200"); // 0
      addParm("Filename","Filename",""); // 0
    }
    bool initialize(QWidget* parent);

    bool run()
    {
      Mesh* m = currentMesh();
      return run(m, parm("Discretization Points").toInt(), parm("Filename"));
    }
    bool run(Mesh* m, int discretization, QString filename);
  };


  class mgxBase_EXPORT CollapseBezier : public Process
  {
    public:
      CollapseBezier(const Process& process) : Process(process)
      {
      setName("Misc/Bezier/Collapse Bezier Points");
      setDesc("Collapse the 2D Bezier gridpoints into a line");
      setIcon(QIcon(":/images/Bezier.png"));
      }

      bool run();
  };

   /**
   * \class NewBezier <BezierProcess.hpp>
   */
  class mgxBase_EXPORT NewBezierRing : public Process {
  public:
    NewBezierRing(const Process& process) : Process(process)
    {
      setName("Misc/Bezier/New Bezier Ring");
      setDesc("New Bezier ring from parameters.");
      setIcon(QIcon(":/images/Bezier.png"));

      addParm("Controls X","Nb of control points in X","12"); // 0
      addParm("Radius X","Physical size along X (um)","100"); // 2
      addParm("Radius Y","Physical size along Y (um)","100"); // 3
    }

    bool initialize(QWidget* parent) { return true; }

    bool run() {
      return run(parm("Controls X").toInt(), parm("Radius X").toFloat(),
        parm("Radius Y").toFloat());
    }

    bool run(uint bezPointsX, float sizeX, float sizeY);
  };

   /**
   * \class NewBezier <BezierProcess.hpp>
   */
  class mgxBase_EXPORT NewBezierRingFromSelected : public Process {
  public:
    NewBezierRingFromSelected(const Process& process) : Process(process)
    {
      setName("Misc/Bezier/New Bezier Ring From Selected Cells");
      setDesc("New Bezier ring from parameters.");
      setIcon(QIcon(":/images/Bezier.png"));

      addParm("Controls X","Nb of control points in X","12"); // 0
      addParm("Radius X","Physical size along X (um)","100"); // 2
      addParm("Radius Y","Physical size along Y (um)","100"); // 3
      addParm("Mode","Mode","3D", QStringList() << "2D" << "3D"); // 3
    }

    bool initialize(QWidget* parent) { return true; }

    bool run() {
      Mesh* m = currentMesh();
      return run(m, parm("Controls X").toInt(), parm("Radius X").toFloat(),
        parm("Radius Y").toFloat(), parm("Mode"));
    }

    bool run(Mesh* m, uint bezPointsX, float sizeX, float sizeY, QString mode);
  };


     /**
     * \class NewBezier <BezierProcess.hpp>
     */
    class mgxBase_EXPORT FlipBezierLine : public Process {
    public:
      FlipBezierLine(const Process& process) : Process(process)
      {
        setName("Misc/Bezier/Flip Bezier Line");
        setDesc("New Bezier ring from parameters.");
        setIcon(QIcon(":/images/Bezier.png"));

      }

      bool initialize(QWidget* parent) { return true; }

      bool run() {
        Mesh* m = currentMesh();
        return run(m);
      }

      bool run(Mesh* m);
    };





}

#endif
