#include <graphmisc.h>
#include <vrmlconvert.h>

// Presently diffuseColor is only attribute supported.
boolc vrmlconvert::equalattributes
(
  vrmlshape const & s, 
  vrmlshaperaw const & raw 
) const
{
  if (s.diffuseColor[0] != (float) raw.diffuseColor[0] )
    return false;

  if (s.diffuseColor[1] != (float) raw.diffuseColor[1] )
    return false;

  if (s.diffuseColor[2] != (float) raw.diffuseColor[2] )
    return false;

  return true;
}


void vrmlconvert::writeattributes
(
  vrmlshape & s, 
  vrmlshaperaw const & raw 
) const
{
  s.diffuseColor[0] = raw.diffuseColor[0];
  s.diffuseColor[1] = raw.diffuseColor[1];
  s.diffuseColor[2] = raw.diffuseColor[2];
}


boolc vrmlconvert::validcoord
( 
  vector<uint> & coord1,
  vector<int> const & coord2,
  int const N
) const 
{
  assert(!coord2.empty());
  if (coord2.empty())
    return false;

  uintc imax = coord2.size();
  for (uint i=0; i<imax; ++i)
  {

    if ( ((i+1)%4)==0 )
    {
      assert(coord2[i]==-1);
      if (coord2[i]!=-1)
        return false;
    }
    else
    {
      // 0 <= coord2[i] < N

      assert( coord2[i]<N );
      if (coord2[i]>=N)
        return false;

      assert(coord2[i]>=0);
      if (coord2[i]<0)
        return false;

      coord1.push_back( coord2[i] );
    }
  }

  assert( (coord1.size()%3)==0 );
  if (! ((coord1.size()%3)==0) )
    return false;

  return true;
}


void vrmlconvert::writepointsandnormals
(
  vrmlshape & s, 
  vrmlshaperaw const & raw 
) const
{
  assert(raw.point.size()==raw.normal.size());

  uintc N = raw.point.size();
  if (N!=raw.normal.size())
    return;

  assert(N!=0);
  if (N==0)
    return;

  assert((N%3)==0);
  if ((N%3)!=0)
    return;

  vector<uint> coord;
  if (! validcoord(coord,raw.coordIndex,N/3) )
    return;

  uintc imax = coord.size();
  uint index;
  for (uint i=0; i<imax; ++i)
  {
    index = coord[i]*3;
    s.point.push_back( raw.point[index] );
    s.point.push_back( raw.point[index+1] );
    s.point.push_back( raw.point[index+2] );
    s.normal.push_back( raw.normal[index] );
    s.normal.push_back( raw.normal[index+1] );
    s.normal.push_back( raw.normal[index+2] );
  }
}

boolc vrmlconvert::hastriangles
(
  vector< vrmlshaperaw > const & v 
) const
{
cout << SHOW(v.size()) << endl;
  if (v.empty())
    return false;

  // Determine if there are shapes to write. 
  uintc imax = v.size();
  for (uint i=0; i<imax; ++i)
  {
    if(v[i].istriangles)
      return true;
  }

  return false;
}

boolc vrmlconvert::eval
(
  vector< vrmlshape > & s,
  vrmlshapeparse const & p
) const
{
  vector< vrmlshaperaw > const & v(p.vshp);

  if(!hastriangles(v))
    return false;

  // Iterate writing shapes.
  vrmlshape * curr = 0;

  uintc imax = v.size();
  for (uint i=0; i<imax; ++i)
  {
    if (!v[i].istriangles)
      continue;

    if (s.empty())
    {
      s.push_back(vrmlshape());
      curr = & s.back();
      writepointsandnormals(*curr,v[i]); 
      writeattributes(*curr,v[i]);
    }
    else
    {
      curr = & s.back();
      if (equalattributes(*curr,v[i]))
      {
        writepointsandnormals(*curr,v[i]); 
      }
      else
      {
        s.push_back(vrmlshape());
        writepointsandnormals(*curr,v[i]); 
        writeattributes(*curr,v[i]);
      }
    }
  }

  return true;
}






