//-----------------------------------------------------------------------------
// findSelected() -- find the selected graphic from the 'select buffer'.
//
// 1) When item == 0, returns nearest (by depth buffer) entry.
// 2) When item < 0, returns furthest (by depth buffer) entry.
// 3) When item > 0, returns the item'th selected entry or the first entry if
//    there are less than 'item' entries
// 4) Returns zero(0) when there are no entries in the select buffer or if the
//    Graphic for the select ID is not found.
//-----------------------------------------------------------------------------
BasicGL::Graphic* FoxDisplay::findSelected(const GLuint sbuff[], const int size, const int item)
{
   BasicGL::Graphic* sel = nullptr;
   GLuint id = 0;

   GLuint dmin = 0;
   GLuint dmax = 0;
   int cnt = 0;
   int idx = 0;
   while (idx < size && sbuff[idx] > 0) {
      int n = sbuff[idx++];           // Number of select names
      GLuint xmin = sbuff[idx++];     // Min Depth
      GLuint xmax = sbuff[idx++];     // Max Depth

      // First select name only
      GLuint xId = sbuff[idx++];
      for (int i = 1; i < n; i++) { idx++; }

      if (cnt == 0) {
         // First item
         id = xId;
         dmin = xmin;
         dmax = xmax;
      }
      else if (item == 0 && xmin < dmin) {
         // Nearest --
         dmin = xmin;
         id = xId;
      }
      else if (item < 0 && xmax > dmax) {
         // Nearest --
         dmax = xmax;
         id = xId;
      }
      else if (item == (cnt+1)) {
         id = xId;
      }
      cnt++;
   }

   // Find the Graphic with this id
   if (id > 0) {
      //std::cout << "selected id = " << id << std::endl;
      Basic::Pair* pair = findBySelectName(id);
      if (pair != nullptr) {
         sel = dynamic_cast<BasicGL::Graphic*>(pair->object());
         if (sel != nullptr) {
            return sel;
         }
      }
   }
   return sel;
}
//-----------------------------------------------------------------------------
// findSelected() -- find the selected graphic from the 'select buffer'.
//
// 1) When item == 0, returns nearest (by depth buffer) entry.
// 2) When item < 0, returns furthest (by depth buffer) entry.
// 3) When item > 0, returns the item'th selected entry or the first entry if
//    there are less than 'item' entries
// 4) Returns zero(0) when there are no entries in the select buffer or if the
//    Graphic for the select ID is not found.
//-----------------------------------------------------------------------------
BasicGL::Graphic* GlutDisplay::findSelected(const GLint hits, const GLuint sbuff[], const int item)
{
   Graphic* sel = nullptr;
   GLuint id = 0;

   // ---
   // Build a list of hit names with their z values
   // ---
   static const unsigned int MAX_HITS = 64;
   GLuint hitList[MAX_HITS];
   GLuint zminList[MAX_HITS];
   GLuint zmaxList[MAX_HITS];
   unsigned int hitCnt = 0;

   unsigned int idx = 0;
   for (GLint hit = 1; hit <= hits && hitCnt < MAX_HITS; hit++) {
      GLuint n   = sbuff[idx++];     // Number of select names
      GLuint zmin = sbuff[idx++];    // Min Depth
      GLuint zmax = sbuff[idx++];    // Max Depth
      if (n > 0) {
         hitList[hitCnt] = sbuff[idx];
         zminList[hitCnt] = zmin;
         zmaxList[hitCnt] = zmax;
         hitCnt++;
      }
      for (GLuint i = 0; i < n; i++) idx++; // move past the stack
   }

   // ---
   // We have at least one hit
   // ---
   if (hitCnt > 0) {

      // Select this item (if it exists)
      if (item > 0 && item <= static_cast<int>(hitCnt)) {
         id = hitList[item-1];
      }

      // Or look for the nearest
      else if (item == 0) {
         // (find the smallest zmin)
         GLuint h = hitList[0];
         GLuint zmin = zminList[0];
         for (unsigned int i = 1; i < hitCnt; i++) {
            if (zminList[i] < zmin) {
               h = hitList[i];
               zmin = zminList[i];
            }
         }
         id = h;
      }

      // Or look for the furthest
      else if (item < 0) {
         // (find the largest zmax)
         GLuint h = hitList[0];
         GLuint zmax = zmaxList[0];
         for (unsigned int i = 1; i < hitCnt; i++) {
            if (zmaxList[i] > zmax) {
               h = hitList[i];
               zmax = zmaxList[i];
            }
         }
         id = h;
      }

   }

   // ---
   // Find the Graphic with this id
   // ---
   if (id > 0) {
      Basic::Pair* pair = findBySelectName(id);
      if (pair != nullptr) {
         sel = static_cast<Graphic*>(pair->object());
      }
   }

   return sel;
}