// nUtil - An utility Library for gnurbs
// Copyright (C) 2008-2026 Eric Bechet
//
// See the LICENSE file for contributions and license information.
// Please report all bugs and problems to <bechet@cadxfem.org>.
//

#ifndef __NDATA_H
#define __NDATA_H

#include <vector>
#include <string>
#include "npoint.h"


class infobase
{
public :
  std::string info;
};

class point : public infobase
{
public:
  point() {}
  point(npoint3 pt1) {pts=pt1;}
  npoint3 pts;
};

class line : public infobase
{
public:
  line() {}
  line(npoint3 pt1,npoint3 pt2) {pts[0]=pt1;pts[1]=pt2;}
  npoint3 pts[2];
};

class triangle : public infobase
{
public:
  triangle() {}
  triangle(npoint3 pt1,npoint3 pt2,npoint3 pt3) {pts[0]=pt1;pts[1]=pt2;pts[2]=pt3;}
  npoint3 pts[3];
};

class quad : public infobase
{
public:
  quad() {}
  quad(npoint3 pt1,npoint3 pt2,npoint3 pt3,npoint3 pt4) {pts[0]=pt1;pts[1]=pt2;pts[2]=pt3;pts[3]=pt4;}
  npoint3 pts[4];
};


class nmesh
{
public:
  enum eltype {NIL=0, POINT,LINE,TRIANGLE,TETRAHEDRON};
  struct nnode
  {
    nnode(void) : num(-1),xyz(),uvw() {}
    nnode(int num_) : num(num_),xyz(),uvw() {}
    nnode(int num_,const npoint3 &pt_) : num(num_),xyz(pt_),uvw() {}
    nnode(int num_,const npoint3 &pt_,const npoint3 &pt_uvw) : num(num_),xyz(pt_),uvw(pt_uvw) {}
    nnode(const npoint3 &pt_) : num(-1),xyz(pt_),uvw() {}
    npoint3 xyz;
    npoint3 uvw;
    long num;
  };
  struct nelement
  {
    nelement(eltype t) : type(t),num(-1)
    {
      for (int i=0;i<4;++i) pts[i]=-1;
    }
    nelement(const nelement &other) : type(other.type),num(-1)
    {
      for (int i=0;i<4;++i) pts[i]=other.pts[i];
    }
    int pts[4];
    eltype type;
    long num;
  };
  int add_node(const nnode& src)
  {
    nodes.push_back(src);
    return nodes.size()-1;
  }
  int nb_nodes(void) const
  {
    return nodes.size();
  }
  nnode& get_node(size_t i)
  {
    return nodes[i];
  }
  const nnode& get_node(size_t i) const
  {
    return nodes[i];
  }
  void clear(void)
  {
    nodes.clear();
    elements.clear();
  }

  int add_element(const nelement& src)
  {
    elements.push_back(src);
    return elements.size()-1;
  }
  int nb_elements(void) const
  {
    return elements.size();
  }
  nelement& get_element(size_t i)
  {
    return elements[i];
  }
  const nelement& get_element(size_t i) const
  {
    return elements[i];
  }
private:
  std::vector<nnode> nodes;
  std::vector<nelement> elements;
};

struct color
{
  color(unsigned char r=255,unsigned char g=255,unsigned char b=255,unsigned char a=255) : R(r),G(g),B(b),A(a) {}
  unsigned char R;
  unsigned char G;
  unsigned char B;
  unsigned char A; //Alpha
};

struct properties
{
  properties() : c(),thickness(1.),edgeon(),edgethickness(1.),edgecolor(),teston(),pointsize(1.) {}
  color c;
  float thickness;
  float pointsize;
  bool edgeon;
  float edgethickness;
  color edgecolor;
  bool teston;
};

class data_container
{
  std::vector<point> points;
  std::vector<std::pair<properties,int> > proppoints;
  std::vector<line> lines;
  std::vector<std::pair<properties,int> > proplines;
  std::vector<triangle> triangles;
  std::vector<std::pair<properties,int> > proptriangles;
  std::vector<quad> quads;
  std::vector<std::pair<properties,int> > propquads;
  std::vector<std::pair<point,color> > texts[3];
  
public :
  data_container(void);
  void clear(void);
  
  const color& getcolorpoints(int i=0) const;
  const color& getcolorlines(int i=0) const;
  const color& getcolortriangles(int i=0) const;
  const color& getcolorquads(int i=0) const;  

  const properties& getproppoints(int i) const; 
  const properties& getproplines(int i) const;
  const properties& getproptriangles(int i) const;
  const properties& getpropquads(int i) const;

  const properties getproppoints() const;
  const properties getproplines() const;
  const properties getproptriangles() const;
  const properties getpropquads() const;

  int getindexpoints(int i=0) const;
  int getindexlines(int i=0) const;
  int getindextriangles(int i=0) const;
  int getindexquads(int i=0) const;


  int getnumproppoints(void) const;
  int getnumproplines(void) const;
  int getnumproptriangles(void) const;
  int getnumpropquads(void) const;


  void setcolorpoints(color c);
  void setcolorlines(color c);
  void setcolortriangles(color c);
  void setcolorquads(color c);

  void setproppoints(properties p);
  void setproplines(properties p);
  void setproptriangles(properties p);
  void setpropquads(properties p);
  
  void add_point(const npoint3& src);
  void add_point(const point& src);
  void add_line(const line& src);
  void add_triangle(const triangle& src);
  void add_quad(const quad& src);
  void add_text(int num,const std::pair<point,color>& src);

  int nb_points(void) const;
  int nb_lines(void) const;
  int nb_triangles(void) const;
  int nb_quads(void) const;
  int nb_texts(int num) const;

  const point& get_point(int i) const;
  const line& get_line(int i) const;
  const triangle& get_triangle(int i) const;
  const quad& get_quad(int i) const;
  const point& get_text(int num,int i) const;
  const color& get_text_color(int num,int i) const;
};


#endif // __NDATA_H
