//
// 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 ITKFILTER_HPP
#define ITKFILTER_HPP

#include <ITKConfig.hpp>
#include <ITKProcess.hpp>

namespace mgx 
{
  class mgxITK_EXPORT ITKSmoothingRecursiveGaussianImageFilter : public Process {
  public:
    ITKSmoothingRecursiveGaussianImageFilter(const Process& process) : Process(process) 
    {
	  setName("Stack/ITK/Filters/ITK Smoothing Recursive Gaussian Image Filter");
	  setDesc("Smoothing Recursive Gaussian Blur");
	  setIcon(QIcon(":/images/Blur.png"));

	  addParm("Radius (µm)","Radius (µm)","1.0");				
	}
  
    bool run()
    {
      if(!checkState().store(STORE_NON_EMPTY))
        return false;
      Stack* s = currentStack();
      Store* input = s->currentStore();
      Store* output = s->work();
      bool res = run(input, output, parm("Radius (µm)").toFloat());
      if(res) {
        input->hide();
        output->show();
      }
      return res;
    }
  
    bool run(const Store* input, Store* output, float radius);
  
  };
  
  class mgxITK_EXPORT ITKCurvatureFlowImageFilter : public Process {
  public:
    ITKCurvatureFlowImageFilter(const Process& process) : Process(process) 
    {
	  setName("Stack/ITK/Filters/ITK Curvature Flow Image Filter");
	  setDesc("Curvature Flow Edge Preserving Smoothing");
	  setIcon(QIcon(":/images/Blur.png"));

	  addParm("TimeStep","TimeStep",".0.0625");
	  addParm("Steps","Steps","10");						
	}
  
    bool run()
    {
      if(!checkState().store(STORE_NON_EMPTY))
        return false;
      Stack* s = currentStack();
      Store* input = s->currentStore();
      Store* output = s->work();
      bool res = run(input, output, parm("TimeStep").toFloat(), parm("Steps").toInt());
      if(res) {
        input->hide();
        output->show();
      }
      return res;
    }
  
    bool run(const Store* input, Store* output, float timestep, int steps);
  
  };
  
  class mgxITK_EXPORT ITKCurvatureAnisotropicDiffusionImageFilter : public Process {
  public:
    ITKCurvatureAnisotropicDiffusionImageFilter(const Process& process) : Process(process) 
    {
	  setName("Stack/ITK/Filters/ITK Curvature Anisotropic Diffusion Image Filter");
	  setDesc("Curvature Anisotropic Diffusion");
	  setIcon(QIcon(":/images/Blur.png"));

	  addParm("TimeStep","TimeStep","0.03");
	  addParm("Iterations","Iterations","5");
	  addParm("Conductance","Conductance","9.0");				
	}
  
    bool run()
    {
      if(!checkState().store(STORE_NON_EMPTY))
        return false;
      Stack* s = currentStack();
      Store* input = s->currentStore();
      Store* output = s->work();
      bool res = run(input, output, parm("TimeStep").toFloat(), parm("Iterations").toInt(), parm("Conductance").toFloat());
      if(res) {
        input->hide();
        output->show();
      }
      return res;
    }
  
    bool run(const Store* input, Store* output, float timestep, int iterations, float conductance);
  
  };
  
  class mgxITK_EXPORT ITKGradientMagnitudeRecursiveGaussianImageFilter : public Process {
  public:
    ITKGradientMagnitudeRecursiveGaussianImageFilter(const Process& process) : Process(process) 
    {
	  setName("Stack/ITK/Filters/ITK Gradient Magnitude Recursive Gaussian Image Filter");
	  setDesc("Gradient Magnitude Recursive Gaussian");
	  setIcon(QIcon(":/images/Blur.png"));

	  addParm("Sigma (µm)","Sigma (µm)","0.5");	
		
		}
  
    bool run()
    {
      if(!checkState().store(STORE_NON_EMPTY))
        return false;
      Stack* s = currentStack();
      Store* input = s->currentStore();
      Store* output = s->work();
      bool res = run(input, output, parm("Sigma (µm)").toFloat());
      if(res) {
        input->hide();
        output->show();
      }
      return res;
    }
  
    bool run(const Store* input, Store* output, float sigma);
  
  };
  
  class mgxITK_EXPORT ITKSigmoidImageFilter : public Process {
  public:
    ITKSigmoidImageFilter(const Process& process) : Process(process) 
    {
	  setName("Stack/ITK/Filters/ITK Sigmoid Image Filter");
	  setDesc("Sigmoid Filter");
	  setIcon(QIcon(":/images/Blur.png"));

	  addParm("Alpha","Alpha","1000.0");
	  addParm("Beta","Beta","2000.0");		
	}
  
    bool run()
    {
      if(!checkState().store(STORE_NON_EMPTY))
        return false;
      Stack* s = currentStack();
      Store* input = s->currentStore();
      Store* output = s->work();
      bool res = run(input, output, parm("Alpha").toFloat(), parm("Beta").toFloat());
      if(res) {
        input->hide();
        output->show();
      }
      return res;
    }
  
    bool run(const Store* input, Store* output, float alpha, float beta);
  };
}

#endif
