// Gnurbs - A curve and surface library
// 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>.
//

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include "nbsplinesurface.h"
#include "ndisplay.h"
#include "gnurbscallbacks.h"

struct patch
{
  int p[4][4];
};

void Load_patch(const char *filename,int &patches,int &verticies,std::vector<patch> &bufpatch,std::vector<npoint>  &bufvertex)
{
  int ii;
  float x,y,z;
  int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p;

  FILE *fp;

  if (!(fp = fopen(filename,"r")))
  {
    fprintf(stderr,"Load_patch: Can't open %s\n",filename);
    exit(1);
  }

  if (fscanf(fp,"%i\n",&patches) ==EOF)
  {
    bufpatch.clear();
    patches = 0;
    bufvertex.clear();
    verticies=0;
    fclose(fp);
    return;
  }
  bufpatch.resize(patches);
  for (ii = 0; ii < patches; ii++)
  {
    if (fscanf(fp,"%i, %i, %i, %i,",&a,&b,&c,&d) ==EOF)
    {
      bufpatch.clear();
      patches = 0;
      bufvertex.clear();
      verticies=0;
      fclose(fp);
      return;
    }
    if (fscanf(fp,"%i, %i, %i, %i,",&e,&f,&g,&h) ==EOF)
    {
      bufpatch.clear();
      patches = 0;
      bufvertex.clear();
      verticies=0;
      fclose(fp);
      return;
    }
    if (fscanf(fp,"%i, %i, %i, %i,",&i,&j,&k,&l) ==EOF)
    {
      bufpatch.clear();
      patches = 0;
      bufvertex.clear();
      verticies=0;
      fclose(fp);
      return;
    }
    if (fscanf(fp,"%i, %i, %i, %i\n",&m,&n,&o,&p) ==EOF)
    {
      bufpatch.clear();
      patches = 0;
      bufvertex.clear();
      verticies=0;
      fclose(fp);
      return;
    }
    bufpatch[ii].p[0][0]=a-1;
    bufpatch[ii].p[0][1]=b-1;
    bufpatch[ii].p[0][2]=c-1;
    bufpatch[ii].p[0][3]=d-1;
    bufpatch[ii].p[1][0]=e-1;
    bufpatch[ii].p[1][1]=f-1;
    bufpatch[ii].p[1][2]=g-1;
    bufpatch[ii].p[1][3]=h-1;
    bufpatch[ii].p[2][0]=i-1;
    bufpatch[ii].p[2][1]=j-1;
    bufpatch[ii].p[2][2]=k-1;
    bufpatch[ii].p[2][3]=l-1;
    bufpatch[ii].p[3][0]=m-1;
    bufpatch[ii].p[3][1]=n-1;
    bufpatch[ii].p[3][2]=o-1;
    bufpatch[ii].p[3][3]=p-1;
  }
  if (fscanf(fp,"%i\n",&verticies) ==EOF)
  {
    bufpatch.clear();
    patches = 0;
    bufvertex.clear();
    verticies=0;
    fclose(fp);
    return;
  }

  bufvertex.resize(verticies);
  for (ii = 0; ii < verticies; ii++)
  {
    if (fscanf(fp,"%f, %f, %f\n",&x,&y,&z) ==EOF)
    {
      bufpatch.clear();
      patches = 0;
      bufvertex.clear();
      verticies=0;
      fclose(fp);
      return;
    }
    bufvertex[ii].w() =1.0;
    bufvertex[ii].wx() =x;
    bufvertex[ii].wy() =y;
    bufvertex[ii].wz() =z;
  }
  fclose(fp);
}


void loadsurfaces(std::string filename,std::vector<nbsplinesurface> &surfs,double X=0., double Y=0.,double Z=0.)
{
  int patches;
  int verticies;
  std::vector<patch> bufpatch;
  std::vector<npoint>bufvertex;
  Load_patch(filename.c_str(),patches,verticies,bufpatch,bufvertex);
  for (int p=0;p<patches;++p)
  {
    nbsplinesurface surf(4,3,4,3);
    for (int i=0;i<4;++i)
    {
      for (int j=0;j<4;++j)
      {
        surf.CP(i,j) =bufvertex[bufpatch[p].p[i][j]]+npoint(X,Y,Z,0);
      }
    }
    for (int i=0;i<4;++i)
    {
      surf.u(i) =surf.v(i) =0.;
      surf.u(i+4) =surf.v(i+4) =1.0;
    }
    surfs.push_back(surf);
  }
}



int main(void)
{
  data_container data;
  ndisplay display;
  gnurbscallbacks CB;
  display.setcallbacks(&CB);
  std::vector<nbsplinesurface> bufsurf;
  loadsurfaces("teaspoon.txt",bufsurf);
  loadsurfaces("teacup.txt",bufsurf,1,1,1);
  loadsurfaces("teapot.txt",bufsurf,3,3,3);
  for (int i=0;i<bufsurf.size();++i)
    CB.add_entity(&bufsurf[i]);
  CB.draw();
  display.init_data(CB.datas);
  display.display();
  return 0;
}
