#ifndef CellAtlasUtils_H
#define CellAtlasUtils_H

#include <Process.hpp> // for vvGraph, forall, ... 
#include <GraphUtils.hpp> // for neighborhoodGraph

#include <ImageData.hpp>
#include <Triangulate.hpp> // calcNearestPointOnBezierLine

using namespace std;

// CellAtlasUtils contains typedefs and class-independent helper-functions for the CellAtlas AddOn
namespace mgx 
{

typedef std::map<int, std::vector<vertex> > labelVertexMap;

typedef std::pair<int, std::vector<vertex> > labelVertexVecPair;

//typedef std::map<int, Point3d> labelPosMap;
//typedef std::map<int, double> labelDataMap;
//typedef std::map<int, bool> labelBoolMap;

// typedef Vector<3, vertex> tri;
// typedef std::vector<tri> triVector;

typedef std::pair<int, int> IntInt;
//typedef std::map<int, triVector> labelTriMap;

typedef std::map<int,std::map<int,double> > cellMorphLandscape;

typedef std::map <int, std::vector<int> > intToVec;

typedef std::map<Point2i, double> P2iDMap;
typedef std::pair<Point2i, double> P2iDPair;
typedef std::pair<IntInt, double> IntIntDouPair;



  /**
   * calculates the neighborhood graph, return data structure for total cell wall area and shared wall area between neighboring cells
   *
   * \param S vvGraph
   * \param tolerance double
   * \param cellAtlasData RootCellProcessing
   *
   * \ingroup CellAtlasUtils
   */
  //bool neighborhoodGraphLocal(const vvGraph& S, double tolerance, RootCellProcessing& cellAtlasData);
  bool neighborhoodGraphLocal(const vvGraph& S, double tolerance, std::map<int, double>& cellWallArea, std::map<IntInt, double>& wallArea, std::map<int, double>& outsideWallArea);

  /**
   * find ONE selected vertex in a vvGraph and return its label
   * return 0 if nothing is selected
   *
   * \param S vvGraph
   *
   * \ingroup CellAtlasUtils
   */
  int findSelectedLabel(const vvGraph& S);

  /**
   * find selected vertices in a vvGraph and return their TWO (different) labels
   * return false if less than two different labels are selected
   *
   * \param S vvGraph
   * \param label1 int first label to return
   * \param label2 int second label to return
   *
   * \ingroup CellAtlasUtils
   */
  bool findTwoSelectedLabels(const vvGraph& S, int& label1, int& label2);


  /**
   * return true if a point is inside a cone
   *
   * \param axisVec Point3d axis vector of the cone (= coneTop - coneBase)
   * \param coneTop Point3d point at the top of the cone
   * \param coneBase Point3d midpoint of the bas of the cone
   * \param coneAngle double angle of the cone (in rad)
   * \param pointToTest Point3d test point
   *
   * \ingroup CellAtlasUtils
   */
  bool pointInCone(Point3d axisVec, Point3d& coneTop, Point3d& coneBase, double coneAngle, Point3d& pointToTest);

  /**
   * returns the value of a 1D gaussian function
   *
   * \param x double input value
   * \param muX double mean value
   * \param sigmaX double standard deviation value
   *
   * \ingroup CellAtlasUtils
   */
  double gauss1D(double x, double muX, double sigmaX);




  
  // TODO documentation



  double calcCircumferential(Point3d dirRadRef, Point3d dirLongRef, Point3d cellCenter, Point3d cellOnLong);

  Point3d inPrimCoord(double radiant, Point3d dirRadRef, Point3d dirLongRef);



    // finds min and max value of a map
  void findMinMax(std::map<int,double>& map, double& min, double& max);




void differentialOfBezierGrid(std::vector<std::vector<Point3d> >& bezierGrid, Point2i& p, Point3d& diffU, Point3d& diffV);


  double cartesianToOrganCoordsLong(Point3d cartesianCoords, std::map<int, Point3d>& bMap, Point3d& closestPoint);



}

#endif
