// 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 "gnurbscallbacks.h"
#include <sstream>

int gnurbscallbacks::pick_callback(int nb, pickinfo picks[],npoint3 p)
{
//  std::cout << "pick num=" << nb << std::endl;
  if (nb)
  {
    for(unsigned int j = 0; j <= 0; j++) // print 1st pick if existing
    {
      std::cout << "t=" << picks[j].type << " id=" << picks[j].id << " ";
      for (int i=0;i<picks[j].nb_uid;++i) 
        std::cout << "uid" << i << "=" << picks[j].uids[i] << " " ;
      std::cout << picks[j].z  << std::endl;
    }
    if (picks[0].nb_uid)
    {
      int objid=picks[0].uids[0];
      picked=objects[objid]->clone();
      return 0; // first element in the stack (closest to the eye) is chosen (-1 if no pick want
    }
  }
  return -1;
}

int gnurbscallbacks::drag_callback(npoint3 orig,npoint3 p, pickinfo pick)
{
  int ret=0;
  npoint delta=npoint(p)-npoint(orig);
//  std::cout << "drag" << std::endl;
//  delta.print(std::cout);
  if (picked)
  {
    if (pick.nb_uid>1) // second uid = CP number
    {
      // move control point
      int objid=pick.uids[0];
      int CPid=pick.uids[1];
      npoint P=picked->CP(CPid);
      objects[objid]->set_CP(CPid,picked->CP(CPid)+delta*P[3]);
//      std::cout << "move CP" << std::endl;
      ret=1;
      draw(objid);
    }
    else if (pick.nb_uid>0)
    {
//      std::cout << "move part" << std::endl;
      // move whole part
      int objid=pick.uids[0];
      for (int i=0;i<picked->nb_CP();++i)
      {

        npoint P=picked->CP(i);
        objects[objid]->set_CP(i,picked->CP(i)+delta*P[3]);
      }
      draw(objid);
      ret=1;
    }
  }
  return ret;
}



int gnurbscallbacks::release_callback(npoint3 orig,npoint3 p, pickinfo pick)
{
  int ret=0;
//  std::cout << "release" << std::endl;
  if (picked)
  {
    npoint delta=npoint(p)-npoint(orig);
//    delta.print(std::cout);
    if (pick.nb_uid>1) // second uid = CP number
    {
      // move control point
      int objid=pick.uids[0];
      int CPid=pick.uids[1];
      npoint P=picked->CP(CPid);
      objects[objid]->set_CP(CPid,picked->CP(CPid)+delta*P[3]);
//      std::cout << "move CP" << std::endl;
      ret=1;
      draw();
    }
    else if (pick.nb_uid>0)
    {
//      std::cout << "move part" << std::endl;
      // move whole part
      int objid=pick.uids[0];
      for (int i=0;i<picked->nb_CP();++i)
      {

        npoint P=picked->CP(i);
        objects[objid]->set_CP(i,picked->CP(i)+delta*P[3]);
      }
      draw();
      ret=1;
    }
    delete picked;
    picked=0x0;
  }
  return ret;
}

std::string gnurbscallbacks::get_info(pickinfo pick)
{
  std::stringstream s;
  if (pick.nb_uid)
  {
    s << objects[pick.uids[0]]->info();
    if (pick.nb_uid>1)
      s << " CP(" << objects[pick.uids[0]]->CP(pick.uids[1]) << ")";
  }
  return s.str();
}

void gnurbscallbacks::draw(void)
{
//  std::cout << "test" << objects.size()<< std::endl;
  for (int i=0;i<objects.size();++i) draw(i);
}

void gnurbscallbacks::draw(int i)
{
  datas[i].clear();
  properties prop=prop_objects[i];
  prop.nb_uid=1;
  prop.uids[0]=i;
  datas[i].setpropall(prop);
  objects[i]->Display(datas[i]);
}
