// File:	TNaming_Selectr.cxx
// Created:	Thu Sep 30 15:07:20 1999
// Author:	Denis PASCAL
//		<dp@dingox.paris1.matra-dtv.fr>


#include <TNaming_Selector.ixx>
#include <TNaming_Naming.hxx>
#include <TNaming_Builder.hxx> 
#include <TNaming_Identifier.hxx>
#include <TNaming_NameType.hxx>
#include <TDF_ChildIterator.hxx> 
#include <TDF_Tool.hxx>
#include <TDF_IDFilter.hxx>

#include <TopTools_MapOfShape.hxx>
#include <TNaming_NamingTool.hxx>

#define BUC60862

#define OCC273
#define OCC351

//=======================================================================
//function : IsIdentified
//purpose  : 
//=======================================================================
Standard_Boolean TNaming_Selector::IsIdentified (const TDF_Label& L,
						 const TopoDS_Shape& Selection, 
						 Handle(TNaming_NamedShape)& NS,
						 const Standard_Boolean Geometry)
{  
  TopoDS_Shape Context;
  Standard_Boolean OnlyOne =!Geometry;
  TNaming_Identifier Ident(L,Selection,Context,OnlyOne);   
  if (Ident.IsFeature()) {  
    if   (!OnlyOne)  return 0;
    else {
      NS =   Ident.FeatureArg();

#ifdef OCC273
      // mpv : external condition
      TDF_LabelMap Forbiden,Valid;
      TopTools_MapOfShape MS;
      TNaming_NamingTool::CurrentShape(Valid,Forbiden,NS,MS);
      return (MS.Contains(Selection) && MS.Extent() == 1);
#else
      return 1;
#endif
    }
  }
  return 0;
}

//=======================================================================
//function : TNaming_Selector
//purpose  : 
//=======================================================================

TNaming_Selector::TNaming_Selector (const TDF_Label& L) 
{
  myLabel = L;
}


//=======================================================================
//function : Select
//purpose  : 
//=======================================================================
Standard_Boolean TNaming_Selector::Select (const TopoDS_Shape& Selection, 
					   const TopoDS_Shape& Context,
					   const Standard_Boolean Geometry) const
{
  myLabel.ForgetAllAttributes();  
  Handle(TNaming_NamedShape)NS;
  if (!IsIdentified (myLabel,Selection,NS,Geometry)) {
    NS = TNaming_Naming::Name (myLabel,Selection,Context,Geometry);
  }
  if (NS.IsNull()) return Standard_False; 
  //
  // namedshape with SELECTED Evolution
  //
  TNaming_Builder B (myLabel);
#ifdef OCC351
  // mpv: if oldShape for selection is some shape from used map of shapes,
  //      then naming structure becomes more complex, can be cycles
  B.Select(Selection,Selection);
#else
  B.Select(Selection,Context);
#endif
  //
  // naming with IDENTITY NameType
  //
  Handle(TNaming_Naming) N = new TNaming_Naming (); 
  N->ChangeName().Type(TNaming_IDENTITY);  
  N->ChangeName().Append(NS);

#ifdef BUC60862
// inserted by vro 06.09.00:
  N->ChangeName().ShapeType(Selection.ShapeType());
#endif

  myLabel.AddAttribute(N);  
  return Standard_True; 
}

//=======================================================================
//function : Select
//purpose  : 
//=======================================================================
Standard_Boolean TNaming_Selector::Select (const TopoDS_Shape& Selection,
					   const Standard_Boolean Geometry) const
{  
  // we give a Null shape. How to guess what is the good context ?
  TopoDS_Shape Context;
//  return Select (Selection,Context,Geometry);
// temporary!!!
  return Select (Selection,Selection,Geometry);

}

//=======================================================================
//function : Solve
//purpose  : 
//=======================================================================
Standard_Boolean TNaming_Selector::Solve (TDF_LabelMap& Valid) const
{
  Handle(TNaming_Naming) name;
  if (myLabel.FindAttribute(TNaming_Naming::GetID(),name)) {
    return name->Solve(Valid);
  }
  return Standard_False;
}

//=======================================================================
//function : Arguments
//purpose  : 
//=======================================================================
void TNaming_Selector::Arguments (TDF_AttributeMap& args) const
{  
  TDF_Tool::OutReferences(myLabel,args);
}

//=======================================================================
//function : TNaming_Selector
//purpose  : 
//=======================================================================

Handle(TNaming_NamedShape) TNaming_Selector::NamedShape() const
{
  Handle(TNaming_NamedShape) NS;
  myLabel.FindAttribute(TNaming_NamedShape::GetID(),NS);
  return NS;
}
