// GenFem - A high-level finite element library
// Copyright (C) 2010-2026 Eric Bechet
//
// See the LICENSE file for license information and contributions.
// Please report all bugs and problems to <bechet@cadxfem.org>.

#ifndef _HELMHOLTZ_MULTLAG_INTERFACEDOMAIN_H_
#define _HELMHOLTZ_MULTLAG_INTERFACEDOMAIN_H_

#include <string>
#include <vector>
#include "scalar_helmholtz_domain.h"
#include "genSupports.h"
#include "genTerm.h"
#include "genTensors.h"
#include "genDataIO.h"
#include "genMatrix.h"
#include "genFilters.h"
#include <OctreeInternals.h>

class InterfaceDomain : public genSupport
{
  public: 
    std::set<long int>* filteredVertices;
 public :
  InterfaceDomain(const genSupport &s) : genSupport() , filteredVertices(NULL) {
  dim = s.dim; 
  tag =s.tag;
  }
  
  
  void NumFilteredVertices(){
    if(!filteredVertices){
      filteredVertices = new std::set<long int>();
      std::map<MVertex*, int> VerticesVector; 
      std::vector<MElement*> ElementsVector;
      genGroupOfElements::elementContainer::const_iterator it;
      for( it = begin(); it != end(); it++){
	ElementsVector.push_back(*it);
	FillVerticesVector(VerticesVector, *it);
      }
      std::map<MVertex*, int>::const_iterator itv;
      for( itv= VerticesVector.begin(); itv !=VerticesVector.end(); itv++){
	if(itv->second == 1)
	  filteredVertices->insert(itv->first->getNum());
      }
    }      
  }
  
  void FillVerticesVector(std::map<MVertex*, int> &VerticesVector, MElement* ele){
  
    std::vector<MVertex*> v;
    ele->getVertices(v);
    std::vector<MVertex*> UnknownVertices;
    std::map<MVertex*, int> KnownVertices;
    std::map<MVertex*, int>::iterator itv;
    for(int i =0; i< v.size(); i++){
      itv = VerticesVector.find(v[i]);
      	if(itv != VerticesVector.end())
	  KnownVertices.insert(std::pair<MVertex*, int>(itv->first, itv->second));
	else
	  UnknownVertices.push_back(v[i]);
    }
    if(KnownVertices.size() == v.size()){
      return;
    }
    else if(KnownVertices.size() !=0){
      int flag = 0;
      for(itv = KnownVertices.begin() ; itv != KnownVertices.end() ;itv ++){
	if(itv->second == 1)
	  flag = 1;
	  break;
      }
      if(flag){
	for(int j = 0; j< UnknownVertices.size() ; j++)
	  VerticesVector[UnknownVertices[j]] = 0;
      }
      else
	setTypeVetices(VerticesVector, UnknownVertices);
    } 
    else{
      setTypeVetices(VerticesVector, v);
    }
  }
   
  void setTypeVetices(std::map<MVertex*, int> &VerticesVector,const std::vector<MVertex*>& v){
    for(int i = 0; i< v.size(); i++){
      std::vector<MVertex*> NeighbourV;
      genGroupOfElements::elementContainer::const_iterator it;
      for( it = begin() ; it != end() ; it++){
	std::vector<MVertex*> v2;
	(*it)->getVertices(v2);
	std::vector<MVertex*>::iterator itv;
	itv = std::find(v2.begin(), v2.end(),v[i]);
	if(itv != v2.end())
	  NeighbourV.insert(NeighbourV.end(), v2.begin(), v2.end());
      }
      std::map<MVertex*, int>::iterator itv;
      int flag =0;
      for(int j =0; j< NeighbourV.size(); j++){
	itv = VerticesVector.find(NeighbourV[j]);
	  if(itv != VerticesVector.end()){
	    if(itv->second == 1){
	      flag = 1;
	      break;
	    }
	  }
      }
      if(flag)
	VerticesVector[v[i]] = 0;
      else
	VerticesVector[v[i]] = 1;
   }
  }
    
  
  
  
  
  
  
  
  virtual ~InterfaceDomain() {
    delete filteredVertices;
  }
  
  
};



#endif// _HELMHOLTZ_MULTLAG_INTERFACEDOMAIN_H_
