/*
    C++ Mesh Generation Library
    Copyright (c) 2000echet <eric at bechet dot ca>

    This file is part of the C++ Mesh Generation Library.

    See the NOTICE & LICENSE files for conditions.
*/
#include "gmshElement.h"
#include "gmshNode.h"

namespace FM
{
  void gmshElement::GetNodes ( vector<gmshNode> &tab ) const
  {
    int n=pgmsh->getNumVertices();
    for (int i=0;i<n;++i)
      tab.push_back(gmshNode(pgmsh->getVertex(i)));
/*    int sz=paomd->size ( 0 );

    for ( int i=0; i<sz; i++ )
    {
      tab.push_back ( gmshNode ( ( gmsh::mVertex * ) paomd->get ( 0,i ) ) );
    }*/
  }

  void gmshElement::GetNeighbors ( vector<gmshElement> &tab ) const
  {
    std::map<MElement*,std::vector<MElement*> >::iterator v=FM::FMModel::Ptr->ele_to_ele.find(pgmsh);
    if (v!=FM::FMModel::Ptr->ele_to_ele.end())
    {
      for (int i=0;i<v->second.size();++i)
      {
        MElement *ele=v->second[i];
//        if (ele->getDim()==dim)
          tab.push_back(gmshElement(ele));
      }
    }
  }


  void gmshElement::CommonNodes ( const gmshElement &other,vector<gmshNode> &tabcommon,vector<gmshNode> &tabother ) const
  {
    vector<gmshNode> curr,oth;
    GetNodes ( curr );
    other.GetNodes ( oth );

    for ( int i=0; i<curr.size(); ++i )
    {
      vector<gmshNode>::iterator it;
      it=find ( oth.begin(),oth.end(),curr[i] );

      if ( it==oth.end() )
      {
        tabother.push_back ( curr[i] );
      }
      else
      {
        tabcommon.push_back ( curr[i] );
      }
    }
  }

  void gmshElement::CommonNodes ( const gmshElement &other,vector<gmshNode> &tabcommon,vector<gmshNode> &tabother,vector<gmshNode> &tabother2 ) const
  {
    vector<gmshNode> curr,oth;
    GetNodes ( curr );
    other.GetNodes ( oth );

    for ( int i=0; i<curr.size(); ++i )
    {
      vector<gmshNode>::iterator it;
      it=find ( oth.begin(),oth.end(),curr[i] );

      if ( it==oth.end() )
      {
        tabother.push_back ( curr[i] );
      }
      else
      {
        tabcommon.push_back ( curr[i] );
        oth.erase ( it );
      }
    }

    tabother2=oth;
  }

  void FMModel::buildAdj ( int code)
  {
    Els.reserve(50000);
    if (code&4) //dim==3
    {
      GModel::riter it=this->firstRegion();
      GModel::riter itf=this->lastRegion();
      for (;it!=itf;++it)
      {
        GRegion * M=*it;
        for( int i=0 ; i<M->tetrahedra.size();++i)
        {
          Els.push_back((MElement*)M->tetrahedra[i]);
        }
      }
    }
//dim==2
    if (code&2)
    {
      GModel::fiter it=this->firstFace();
      GModel::fiter itf=this->lastFace();
      for (;it!=itf;++it)
      {
        GFace * M=*it;
        for( int i=0 ; i<M->triangles.size();++i)
        {
          Els.push_back((MElement*)M->triangles[i]);
        }
      }
    }
// dim==1
    if (code&1)
    {
      GModel::eiter it=this->firstEdge();
      GModel::eiter itf=this->lastEdge();
      for (;it!=itf;++it)
      {
        GEdge * M=*it;
        for( int i=0 ; i<M->lines.size();++i)
        {
          Els.push_back((MElement*)M->lines[i]);
        }
      }
    }
//  std::cout << std::endl;
    for (int i=0;i<Els.size();++i)
    {
      for (int j=0;j<Els[i]->getNumVertices();++j)
        v_to_ele[Els[i]->getVertex(j)].push_back(Els[i]);
    }
    for (int i=0;i<Els.size();++i)
    {
      std::map<MElement*,int> s;
      for (int j=0;j<Els[i]->getNumVertices();++j)
      {
        std::vector<MElement*> &tab=v_to_ele[Els[i]->getVertex(j)];
        for (int k=0;k<tab.size();++k)
          s[tab[k]]++;
      }
      for (std::map<MElement*,int>::iterator it=s.begin();it!=s.end();++it)
      {
        if ((it->second==Els[i]->getNumVertices()-1)&&(it->first->getNumVertices()==Els[i]->getNumVertices()))
          ele_to_ele[Els[i]].push_back(it->first);
      }
//      std::cout << Els[i]->getNumVertices() << " " <<  s.size() << " " << ele_to_ele[Els[i]].size() << std::endl;
    }
  }
  FMModel* FMModel::Ptr=NULL;
}


