#include <cassert>
#include <iostream>
using namespace std;

#include <d4tri.h>


// Uninitialized tetrahedron.
d4tri::d4tri()
{
  for (uint i=0; i<4; ++i)
  {
    pi[i] = 0;
    ni[i] = 0;
  }
}

d4tri::d4tri
(
  uintc a,
  uintc b,
  uintc c,
  uintc d,
  uintc na,
  uintc nb,
  uintc nc,
  uintc nd
) 
{ 
  construct(a,b,c,d,na,nb,nc,nd); 
}

/*
void d4tri::solvex(uint & x, uintc a, uintc b, uintc c) const
{
  bool y[4] = { false, false, false, false };

  y[a]=true;
  y[b]=true;
  y[c]=true;
  for (uint i=0; i<4; ++i)
  {
    if (y[i]==false)
    {
      x=i;
      return;
    }
  }

  assert(false);
}
*/



/*
uintc d4tri::getoppvertex
( 
  uintc neib 
) const
{ 
  return pi[ niInverse(neib) ]; 
}
*/



uintc d4tri::piInverse 
(
  bool & res,
  uintc gpt
) const
{
  assert(gpt!=0);

  res=true;

  if (pi[0]==gpt) return 0;
  if (pi[1]==gpt) return 1;
  if (pi[2]==gpt) return 2;
  if (pi[3]==gpt) return 3;

  res=false;
  return 4; // Return crap.
}







/*
uintc d4tri::piInverse 
(
  uintc gpt
) const
{
  assert(gpt!=0);

  if (pi[0]==gpt) return 0;
  if (pi[1]==gpt) return 1;
  if (pi[2]==gpt) return 2;
  if (pi[3]==gpt) return 3;

  assert(false);
  return 4; // Return crap.
}
*/

boolc d4tri::isonboundary() const
{
  if (ni[0]==0) return true;
  if (ni[1]==0) return true;
  if (ni[2]==0) return true;
  if (ni[3]==0) return true;
  
  return false;
}

/*
uintc d4tri::niInverse
(
  uintc neib
) const
{  
  if (ni[0]==neib) return 0;
  if (ni[1]==neib) return 1;
  if (ni[2]==neib) return 2;
  if (ni[3]==neib) return 3;

  assert(false);
  return 4; // Return crap.
}
*/

uintc d4tri::niInverse
(
  bool & res,
  uintc neib
) const
{  
  res=true;

  if (ni[0]==neib) return 0;
  if (ni[1]==neib) return 1;
  if (ni[2]==neib) return 2;
  if (ni[3]==neib) return 3;

  res=false;
  return 4; // Return crap.
}




boolc d4tri::isavertex( uintc gpt ) const
{
  if (gpt==pi[0]) return true;
  if (gpt==pi[1]) return true;
  if (gpt==pi[2]) return true;
  if (gpt==pi[3]) return true;

  return false;
}





ostream & d4tri::print(ostream& os) const
{
  for (uint i=0; i<4; ++i)
    os << pi[i] << " ";

  os << "  ";

  for (uint i=0; i<4; ++i)
    os << ni[i] << " ";

  return os;
}




/*
void d4tri::isneighbour
(
  bool &res,
  uint & index,
  uintc x
)
{
  for (uint i=0; i<4; ++i)
  {
    if (x==ni[i])
    {
      res=true;
      index=i;
      return;
    }
  }

  res=false;
}
*/




void d4tri::construct
(
  uintc a,
  uintc b,
  uintc c,
  uintc d,
  uintc na,
  uintc nb,
  uintc nc,
  uintc nd
)
{
  pi[0] = a;
  pi[1] = b;
  pi[2] = c;
  pi[3] = d;
  ni[0] = na;
  ni[1] = nb;
  ni[2] = nc;
  ni[3] = nd;
};


void d4tri::getanticlockwiseface
(
  uint & a, 
  uint & b, 
  uint & c, 
  uintc face
) const 
{
  switch (face)
  {
    case 0:
      a=2; b=1; c=3;
      break;

    case 1:
      a=0; b=2; c=3;
      break;

    case 2:
      a=1; b=0; c=3;
      break;

    case 3:
      a=0; b=1; c=2;
      break;

    default:
      assert(false);
  }
}

void d4tri::getclockwiseface
(
  uint & a, 
  uint & b, 
  uint & c, 
  uintc face
) const 
{
  switch (face)
  {
    case 0:
      a=3; b=1; c=2;
      break;

    case 1:
      a=3; b=2; c=0;
      break;

    case 2:
      a=3; b=0; c=1;
      break;

    case 3:
      a=2; b=1; c=0;
      break;

    default:
      assert(false);
  }

//  uint a2,c2;
//  getanticlockwiseface(a2,b,c2,face);

//  a=c2;
//  c=a2;
}

boolc d4tri::isnull() const
{
  for (uint i=0; i<4; ++i)
  {
    if (pi[i]!=0)
      return false;

    if (ni[i]!=0)
      return false;
  }

  return true;
}

void d4tri::setnull()
{
  for (uint i=0; i<4; ++i)
  {
    pi[i]=0;
    ni[i]=0;
  }
}

uintc d4tri::sumofpoints() const
{
  return pi[0]+pi[1]+pi[2]+pi[3];
}

boolc d4tri::hassamepoints(d4tri const & w) const
{
  if (sumofpoints()!=w.sumofpoints())
    return false;

  for (uint i=0; i<4; ++i)
  {
    bool res(false);
    for (uint k=0; k<4; ++k)
    {
      if (w.pi[k]==pi[i])
      {
        res=true;
        k=3;
      }
    }
    if (res==false)
      return false;
  }

  return true;
}



ostream & operator << (ostream& os, d4tri const & x)
{ 
  return x.print(os); 
}


