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

#include <Process.hpp>

namespace mgx
{
  class mgxBase_EXPORT SignalOrientation : public Process
  {
  public:
    SignalOrientation(const Process& process) : Process(process) 
    {
      setName("Mesh/Cell Axis/Polarization/Compute Signal Orientation");
      setDesc("Compute principal orientation of signal gradient between cell border and center.");
      setIcon(QIcon(":/images/PDG.png"));  

      addParm("Border Size","Width of cell border that is not taken into account for the computation.","0.5");
      addParm("Minimum inner area ratio","Minimum ratio of inner area (whole cell - border) vs. total area needed for computation.","0.25");    
    }

    bool run()
    {
      if (!checkState().mesh(MESH_NON_EMPTY|MESH_SIGNAL)) 
        return false;
      Mesh* mesh = currentMesh();
      return run(mesh, parm("Border Size").toFloat(), parm("Minimum inner area ratio").toFloat());
    }

    bool run(Mesh* mesh, float border, float minAreaRatio);
  };

  class mgxBase_EXPORT DisplaySignalOrientation: public Process
  {
    public:
      DisplaySignalOrientation(const Process& process) : Process(process) 
      {
      setName("Mesh/Cell Axis/Polarization/Display Signal Orientation");
    setDesc("Display the orientation of gradients of signal between cell center vs border.");
    setIcon(QIcon(":/images/PDG.png"));  

    addParm("Heatmap","Display strength of orientation as a colormap.\n"
      "Ratio = Max_gradient/Min_gradient -1Difference = Max_gradient - Min_gradient","None", 
      QStringList() << "None" << "Ratio" << "Difference" << "BezierX" << "BezierY");
    addParm("Axis","Display principal directions of signal gradient. \n"
      "Ratio -> display only Max orientation, scaled by (Max/Min-1). \n"
      "Difference -> display only Max orientation, scaled by (Max-Min). \n"
      ,"Difference", QStringList() << "None" << "Both" << "Ratio" << "Difference" << "BezierX" << "BezierY");
    addParm("Line Color Max","Color Max direction.","red", QColor::colorNames());
    addParm("Line Color Min","Color Min direction.","green", QColor::colorNames());
    addParm("Line Width","Line Width","5.0");
    addParm("Line Scale","Length of the vectors = Scale * orientation strength.","0.01");
    addParm("Line Offset","Draw the vector ends a bit tilted up for proper display on surfaces.","0.1");
    addParm("Threshold","Minimal value of orientation strength required for drawing main direction. \n"
    "Either use Ratio or Difference, depending on the display Axis option.","0.0");              
   }

     bool run()
     {
       if(!checkState().mesh(MESH_NON_EMPTY))
         return false;

       return run(currentMesh(),parm("Heatmap"), parm("Axis"), QColor(parm("Line Color Max")), 
         QColor(parm("Line Color Min")), parm("Line Width").toFloat(),
         parm("Line Scale").toFloat(), parm("Line Offset").toFloat(), parm("Threshold").toFloat());
      }

    bool run(Mesh *mesh, const QString displayHeatMap, const QString displayAxis, const QColor& qaxisColor1,
               const QColor& qaxisColor2, float axisLineWidth, float axisLineScale, float axisOffset, float orientationThreshold);  

  };

class mgxBase_EXPORT SignalOrientation3D : public Process
  {
  public:
    SignalOrientation3D(const Process& process) : Process(process) 
    {
    setName("Mesh/Cell Axis 3D/Polarization/Compute Signal Orientation");
    setDesc("Compute principal orientation of signal gradient between cell border and center. 3D version for volumetric meshes");
    setIcon(QIcon(":/images/PDG.png")); 
  
  }

    bool run()
    {
        if (!checkState().mesh(MESH_NON_EMPTY|MESH_SIGNAL)) return false;
        Mesh* mesh = currentMesh();
        return run(mesh);
    }

    bool run(Mesh* mesh);
  };


  class mgxBase_EXPORT DisplaySignalOrientation3D: public Process
  {
  public:
    DisplaySignalOrientation3D(const Process& process) : Process(process) 
    {
      setName("Mesh/Cell Axis 3D/Polarization/Display Signal Orientation");
      setDesc("Display the orientation of gradients of signal between cell center vs border. 3D version for volumetric meshes");
      setIcon(QIcon(":/images/PDG.png")); 

      addParm("Heatmap","Display strength of orientation as a colormap.\n"
        "Ratio = Max_gradient/Min_gradient -1Difference = Max_gradient - Min_gradient","None", 
         QStringList() << "None" << "Ratio" << "Difference" << "BezierX" << "BezierY");
      addParm("Axis","Display principal directions of signal gradient. \n"
        "Ratio -> display only Max orientation, scaled by (Max/Min-1). \n"
        "Difference -> display only Max orientation, scaled by (Max-Min). \n"
        ,"Difference", QStringList() << "None" << "All" << "Both" << "Ratio" << "Difference" << "BezierX" << "BezierY");
      addParm("Line Color Max","Color Max direction.","red", QColor::colorNames());
      addParm("Line Color Mid","Color Min direction.","blueviolet", QColor::colorNames());
      addParm("Line Color Min","Color Min direction.","lightgreen", QColor::colorNames());
      addParm("Line Width","Line Width","5.0");
      addParm("Line Scale","Length of the vectors = Scale * orientation strength.","0.01");
      addParm("Threshold","Minimal value of orientation strength required for drawing main direction. \n"
      "Either use Ratio or Difference, depending on the display Axis option.","0.0");             
     }

     bool run()
     {
       if(!checkState().mesh(MESH_NON_EMPTY))
         return false;

       return run(currentMesh(),parm("Heatmap"), parm("Axis"), QColor(parm("Line Color Max")), QColor(parm("Line Color Mid")), 
           QColor(parm("Line Color Min")), parm("Line Width").toFloat(), parm("Line Scale").toFloat(), parm("Threshold").toFloat());
      }

    bool run(Mesh *mesh, const QString displayHeatMap, const QString displayAxis, const QColor& qaxisColor1, const QColor& qaxisColor2,
               const QColor& qaxisColor3, float axisLineWidth, float axisLineScale, float orientationThreshold);  
  };
}
#endif
