#ifndef TYPES_HPP
#define TYPES_HPP
/**
 * \file Types.hpp
 *
 * Type definitions
 */
#include <Config.hpp>

#include <map>
#include <set>
#include <vector>

#include <QString>

#include <cuda/CudaExport.hpp>
#include <Geometry.hpp>
#include <UnorderedMap.hpp>
#include <UnorderedSet.hpp>
#include <SetVector.hpp>

#include <VertexData.hpp>
#include <EdgeData.hpp>
#include <VVGraph.hpp>
#include <CellData.hpp>
#include <WallData.hpp>

namespace mgx 
{
  /**
   * Simpler names for the various containers and iterators
   */
  typedef unsigned short ushort;
  typedef unsigned int uint;
  typedef unsigned long ulong;
  
  typedef Vector<3, bool> Point3b;
  
  /// Map of an integer to a float
  typedef std::unordered_map<int, float> IntFloatMap;
  /// Element in IntFloatMap
  typedef std::pair<int, float> IntFloatPair;

  /// Map of an integer to a 3D point
  typedef std::unordered_map<int, Point3f> IntPoint3fMap;
  /// Element in IntPoint3fMap
  typedef std::pair<int, Point3f> IntPoint3fPair;

  /// Map of Point3d to int
  typedef std::map<Point3d, int> Point3dIntMap;
  /// Element in Point3dIntMap
  typedef std::pair<Point3d, int> Point3dIntPair;

  /// Map of an integer to a double
  typedef std::unordered_map<int, double> IntDoubleMap;
  /// Element in IntDoubleMap
  typedef std::pair<int, double> IntDoublePair;
  /// Map of an integer to a double 3D point
  typedef std::unordered_map<int, Point3d> IntPoint3dMap;
  /// Element in IntPoint3dMap
  typedef std::pair<int, Point3d> IntPoint3dPair;

  /// Map of an integer to another one
  typedef std::unordered_map<int, int> IntIntMap;
  /// Element in IntIntMap
  typedef std::pair<int, int> IntIntPair;
  /// Map of an integer to a host vector of 3 unsigned integers
  typedef std::unordered_map<int, HVec3U> IntHVec3uMap;
  /// Element in IntHVec3uMap
  typedef std::pair<int, HVec3U> IntHVec3uPair;
  /// Set of vertex ids
	typedef std::set<intptr_t> VIdSet;
	/// Map of an integer to a set of vertex ids
  typedef std::map<int, VIdSet> IntVIdSetMap;
  /// Element in IntVIdSetMap
  typedef std::pair<int, VIdSet> IntVIdSetPair;
  /// Set of integers
  typedef std::set<int> IntSet;
  /// Vector of integers
  typedef std::vector<int> IntVec;
  /// Vector of floats
  typedef std::vector<float> FloatVec;
  /// Vector of Point2f
  typedef std::vector<Point2f> Point2fVec;
  /// Element in IntIntSetMap
  typedef std::pair<int, IntSet> IntIntSetPair;
  /// Map of an integer to a set of integers
  typedef std::map<int, IntSet> IntIntSetMap;
  /// Element in IntIntVIdSetMap
  typedef std::pair<IntIntPair, VIdSet> IntIntVIdSetPair;
  /// Element in IntIntFloatMap
  typedef std::pair<IntIntPair, float> IntIntFloatPair;
  /// Map of a pair of integers to a float
  //typedef std::map<IntIntPair, float> IntIntFloatMap;
  typedef std::unordered_map<IntIntPair, float> IntIntFloatMap;
  /// Map of a pair of integers to a set of vertex ids
  typedef std::map<IntIntPair, VIdSet> IntIntVIdSetMap;
  /// Map of an integer to a 3x3 matrix
  //typedef std::map<int, Matrix3f> IntMatrix3x3fMap;
  typedef std::unordered_map<int, Matrix3f> IntMatrix3fMap;
  /// Element in IntMatrix3x3fMap
  typedef std::pair<int, Matrix3f> IntMatrix3fPair;
  /// Map an integer to a symmetric tensor
  typedef std::unordered_map<int, SymmetricTensor> IntSymTensorMap;
  /// Element in IntSymTensorMap
  typedef std::pair<int, SymmetricTensor> IntSymTensorPair;

  /**
   * Simpler names for the various containers and iterators related to vertices and VV
   */

  /// Type of the VV graph holding the actual mesh
  typedef VVGraph<mgx::VertexData, mgx::EdgeData> vvGraph;
  /// Type of a vertex
  typedef vvGraph::vertex_t vertex;
  /// Type of an edge
  typedef vvGraph::edge_t edge;

  /// Type of the cell graph
  typedef VVGraph<mgx::CellData, mgx::WallData> cellGraph; 
  /// Type of a vertex
  typedef cellGraph::vertex_t cell;
  /// Type of an edge
  typedef cellGraph::edge_t wall;
  /// Set of cells
  typedef std::unordered_set<cell> CellSet;
  /// Vector of cells
  typedef std::vector<cell> CellVec;

  /// Set of vertices
  typedef std::set<vertex> VtxSet;
  /// Used with vertex ids
  typedef std::set<uint> UIntSet;
  /// Vector of vertices
  typedef std::vector<vertex> VtxVec;
  /// Vector of vvGraphs
  typedef std::vector<vvGraph> VVGraphVec;
  /// Integer, VVGraph pair
  typedef std::pair<int, vvGraph> IntVVGraphPair;
  /// Vector of vvGraphs
  typedef std::vector<vvGraph *> vvGraphVec;

  /// Map of an integer to a vvGraph
  typedef std::unordered_map<int, vvGraph> IntVVGraphMap;
  /// Int to vertex map
  typedef std::unordered_map<int, vertex> IntVtxMap;
  typedef std::pair<int, vertex> IntVtxPair;
  /// Map of vertex to vertex
  typedef std::unordered_map<vertex, vertex> VtxVtxMap;
  typedef std::pair<vertex, vertex> VtxVtxPair;
  /// Map of vertex to cell
  typedef std::unordered_map<vertex, cell> VtxCellMap;
  /// Map of vertex to int
  typedef std::unordered_map<vertex, int> VtxIntMap;
  /// Map of vertex to bool
  typedef std::unordered_map<vertex, bool> VtxBoolMap;
  /// Map of vertex to float 
  typedef std::unordered_map<vertex, float> VtxFloatMap;
  /// Map of vertex to Point2f
  typedef std::unordered_map<vertex, Point2f> VtxPoint2fMap;
  /// Map of vertex to Point2d
  typedef std::unordered_map<vertex, Point2d> VtxPoint2dMap;
  /// Map of vertex to Point3f
  typedef std::unordered_map<vertex, Point3f> VtxPoint3fMap;
  /// Map of vertex to Point3d
  typedef std::unordered_map<vertex, Point3d> VtxPoint3dMap;
  /// Map of vertex to Matrix3f
  typedef std::unordered_map<vertex, Matrix3f> VtxMatrix3fMap;

  /// Map of an integer to a cellGraph
  typedef std::unordered_map<int, cellGraph> IntCellGraphMap;
  /// Map of cell to cell
  typedef std::unordered_map<cell, cell> CellCellMap;
  typedef std::pair<cell, cell> CellCellPair;
  /// Int to cell map
  typedef std::unordered_map<int, cell> IntCellMap;
  /// Map of cell to int
  typedef std::unordered_map<cell, int> CellIntMap;
  /// Map of cell to bool
  typedef std::unordered_map<cell, bool> CellBoolMap;
  /// Map of cell to float 
  typedef std::unordered_map<cell, float> CellFloatMap;
  /// Map of cell to Point2f
  typedef std::unordered_map<cell, Point2f> CellPoint2fMap;
  /// Map of cell to Point3f
  typedef std::unordered_map<cell, Point3f> CellPoint3fMap;
  /// Map of cell to Matrix3f
  typedef std::unordered_map<cell, Matrix3f> CellMatrix3fMap;
}
#endif
