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

#include <vector>

#include "nutil.h"
#include "ndisplay_base.h"
#include "GL/gl.h"

class nFltkWindow;

struct Fl_Menu_Item;

#define USE_DLISTS

class fltkdisplay: public ndisplay_base
{
#ifdef USE_DLISTS
    std::vector<GLuint> Dlists;
    GLuint Dlist;
#endif

protected :

public:
  fltkdisplay(color _c=color(25, 51, 102,255),const char *_name=NULL); // constructor
  virtual ~fltkdisplay(); // destructor
  virtual void init_data(const std::vector<data_container> &data);   // all
  virtual void init_data(const data_container &data);   // one dataset - will be copied
  virtual void init_data();   // self created
  virtual data_container* get_data() { if ((data2)) return &(*data2)[0];else return 0x0;}
  color get_backgroundcolor() const {return c;}
  const char* get_name() const {return name;}
  virtual const std::vector<data_container>* get_data_all() const { return data;}
  virtual void update_view(); // update view (AA),but does not change viewpoint
  virtual void update_view_X(bool swap=false); // update view (AA), right view -> yz as y -> right, z -> up (x toward)
  // toggles to left view   -> yz as y -> left,  z -> up (x away) 
  virtual void update_view_Y(bool swap=false); // update view (AA), front view -> xz as x -> right, z -> up (y away)
  // toggles to  back view   -> xz as x -> left,  z -> up (y toward)
  virtual void update_view_Z(bool swap=false); // update view (AA), top view   -> xy as x -> right, y -> up (z toward ) (default)
  // toggles to  bottom view   -> yz as y -> left,  z -> up (x away)
  
  virtual void update_view_right(double d=0.);   // set to right view  -> yz as y -> right, z -> up (x toward)
  virtual void update_view_left(double d=0.);    // set to left view   -> yz as y -> left,  z -> up (x away)
  virtual void update_view_front(double d=0.);   // set to front view  -> xz as x -> right, z -> up (y away)
  virtual void update_view_back(double d=0.);    // set to back view   -> xz as x -> left,  z -> up (y toward)
  virtual void update_view_top(double d=0.);     // set to top view    -> xy as x -> right, y -> up (z toward ) (default)
  virtual void update_view_bottom(double d=0.);  // set to bottom view -> yz as y -> left,  z -> up (x away)
    
  virtual void reset_view(); // update view (AA) and change viewpoint to origin
  virtual void update_bb(); // same as above, but only bb updated
  virtual void display();   // display loop
  virtual void draw_model( int mode=DRAW_NORMAL);
  virtual void draw_model_pick();
  virtual void redraw(); // force refresh
  virtual void draw(); // called by the opengl window at every refresh
  virtual void save(const char *fname="default.d3d");
  virtual void load(const char *fname="default.d3d");
  virtual int handle(int event); // called by the opengl window at every event
  virtual void setpick(bool); // update the picking status (also in menu)
  virtual int getnumpick(void); // return max number of pickable elements
  virtual void hide(int seg,int type,int num); // hide entity
  virtual void hide ( int nb_uid, const int uids[] ); // hide all entities with the same tag
  virtual void unhide(void); // unhide all
  virtual pickinfo get_currentpick (void) {if (picking) return  current_pick;else {pickinfo p; p.seg=-1;p.id=-1;p.nb_uid=0;p.type=-1;return p;}}
  virtual std::vector<pickinfo>& get_currentpicks(void) {return current_picks;}
  virtual void add_lights ( void );
  virtual void get_matrices ( void );
  virtual bool get_coords ( GLfloat i,GLfloat j, npoint3 &p,npoint3 &v,GLfloat &z); // computes 3D coordinates from a point picked in screen
  virtual bool get_coords_with_z ( GLfloat i,GLfloat j,GLfloat z, npoint3 &p,npoint3 &v); // computes 3D coordinates from a point picked in screen, knowing z
  virtual bool get_coords ( GLfloat di,GLfloat dj,GLfloat z, npoint3 &p); //  computes 3D coordinates from a point picked in screen after drag (z given)
  virtual void set_viewpoint(double focal_, double fov_,double nearclip_,double farclip_,const double vp_[3],const double look_[3],const double up_[3]);
  virtual void setup_gl(int mode=DRAW_NORMAL,int i=0,int j=0,int di=1,int dj=1);
  virtual void resetup_gl(void);
  virtual void get_viewpoint(double &focal_, double &fov_,double &nearclip_,double &farclip_,double vp_[3],double look_[3],double up_[3]);
  virtual void set_color (::color c_) {c=c_;}
  virtual int pick (int x, int y, std::vector<pickinfo>& picks,int szx=5, int szy=5);
  virtual bool allow_picks(bool p=true) { bool pp=picking; picking=p;return pp;}
  virtual bool individual_picks(bool p=true);
  virtual bool gl_picks(bool p=true);
  void buildMenus(const Fl_Menu_Item *menuitems_custom,void *);
  bool drawlines;
  bool drawpoints;
  bool drawsurfaces;
  bool drawtexts;
  bool AA; // antialiasing
  bool tagid; // ask opengl to tag with individual ids of each primitive
  nFltkWindow *win; // the drawing window
  bool up_to_date; // allows to refresh display lists on the fly if false
private :
  virtual void _draw_model(bool transparent, int mode,int iddata); // draw either solid faces or transparent ones w/o depth update
  virtual void compute_bb();
  virtual void reset_bb();
  const std::vector<data_container> *data;
  std::vector<data_container> *data2; // owned & non const
  color c;
  char *name;
  npoint3 llf,urb;//bounding box
  bool picking;
  bool glpicking;
  pickinfo current_pick;
  npoint3 pickedpoint;
  std::vector<pickinfo> current_picks;
  bool push;
  int xp,yp;
  GLfloat z;
  double focal;
  double fov;
  double nearclip;
  double farclip;
  GLdouble vp[3];
  GLdouble look[3];
  GLdouble up[3];
  double dinit;
  GLdouble ProjectionMatrix[4][4];
  GLdouble ModelViewMatrix[4][4];
  GLdouble Inv[4][4];
  GLint Viewport[4];
  npoint3 orig;
};


#endif// __FLTKDISPLAY_H
