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

#include <Config.hpp>

#include <Geometry.hpp>
#include <MGXViewer/qglviewer.h>
#include <Bezier.hpp> 

namespace mgx
{
  class SetupProcess;

  typedef Vector<2, int> Point2i;
  typedef Vector<3, float> Point3f;
  
  class mgx_EXPORT CuttingSurface : public QObject 
  {
    Q_OBJECT
    friend class SetupProcess;
  
  public:
    CuttingSurface();
    ~CuttingSurface();
  
    enum Mode { PLANE, THREE_AXIS, BEZIER };
  
    Mode mode() const {
      return _mode;
    }
    void setMode(Mode m)
    {
      if(m != _mode) {
        _mode = m;
        hasChanged();
      }
    }

    bool drawGrid() const {
      return _drawGrid;
    }

    void showGrid()
    {
      if(!_drawGrid) {
        _drawGrid = true;
        hasChanged();
      }
    }

    void hideGrid()
    {
      if(_drawGrid) {
        _drawGrid = false;
        hasChanged();
      }
    }
  
    void show()
    {
      if(!_draw) {
        _draw = true;
        hasChanged();
      }
    }
    void hide()
    {
      if(_draw) {
        _draw = false;
        hasChanged();
      }
    }
    bool isVisible() const {
      return _draw;
    }
  
    const Point3f& size() const {
      return _size;
    }
    void setSize(const Point3f& s)
    {
      if(s != _size) {
        _size = s;
        hasChanged();
      }
    }
  
    const Point2i& surfSize() const {
      return _surfSize;
    }
    void setSurfSize(const Point2i& s)
    {
      if(s != _surfSize) {
        _surfSize = s;
        hasChanged();
      }
    }
  
    // Get frame
    qglviewer::ManipulatedFrame& frame() {
      return _frame;
    }
    const qglviewer::ManipulatedFrame& frame() const {
      return _frame;
    }
  
    // Get cutting plane rectangle
    void getSurfPoints(const qglviewer::Frame* stk_frame, std::vector<Point3f>& points, int& uSize, int& vSize);
  
    // Evaluate coordinates on surface
    Point3f evalCoord(float u, float v) const;
    Point3f evalNormal(float u, float v) const;

    // Get bezier object
    const Bezier &bezier() const {
      return _bez;
    }
    Bezier &bezier() {
      return _bez;
    } 

    void hasChanged() {
      _changed = true;
    }
    bool changed() const {
      return _changed;
    }

  protected:
    void resetModified() {
      _changed = false;
    }
  
    Mode _mode;
    bool _drawGrid;
    Point3f _size;
    bool _draw;
    Point2i _surfSize;
    bool _changed;
		Bezier _bez; 
  
    // Clipping plane frame
    qglviewer::ManipulatedFrame _frame;
  };
}
#endif
