// File:        DDataStd_ConstraintCommands.cxx
// Created:     Wed Jul 30 16:14:44 1997
// Author:      Denis PASCAL
//              <dp@dingox.paris1.matra-dtv.fr>

#include <DDataStd.hxx>

#include <DDF.hxx>
#include <Draw_Interpretor.hxx>
#include <Draw_Appli.hxx>

#include <TDF_Data.hxx>
#include <TDF_Label.hxx>
#include <TDF_ChildIterator.hxx>
#include <TDF_Tool.hxx>

#include <TNaming_NamedShape.hxx>

#include <TDataStd.hxx>
#include <TDataStd_Real.hxx>
#include <TDataStd_Integer.hxx>
#include <TDataStd_Constraint.hxx>
#include <TDataStd_PatternStd.hxx>

#include <TCollection_AsciiString.hxx>

#include <Standard_Macro.hxx>

//=======================================================================
//function : DDataStd_SetConstraint
//purpose  : SetConstraint (DF,entry,keyword,geometrie/value[,geometrie])",
//=======================================================================
static Standard_Integer DDataStd_SetConstraint (Draw_Interpretor& di,
                                                Standard_Integer nb, 
                                                char** arg) 
{   
  if (nb < 5)
  {
    di << "usage: SetConstraint DF entry keyword geometrie [geometrie ...]" << "\n";
    di << "or SetConstraint DF entry \"plane\" geometrie - to set plane for existing constraint" << "\n";
    di << "or SetConstraint DF entry \"value\" value - to set value for existing constraint" << "\n";
    return 1;
  }

  Handle(TDF_Data) DF;
  if (!DDF::GetDF(arg[1],DF)) return 1;

  TDF_Label L;     
  if (!DDF::FindLabel(DF,arg[2],L)) return 1;  

  TDataStd_ConstraintEnum aCT;
  char* aT = arg[3];

  if (strcmp(aT,"plane") == 0)
  {
    Handle(TDataStd_Constraint) C;
    if (!L.FindAttribute(TDataStd_Constraint::GetID(), C)) return 1;

    TDF_Label aLab;     
    if (!DDF::FindLabel(DF, arg[4], aLab)) return 1;
    Handle(TNaming_NamedShape) aSh;
    if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aSh))
    {
      C->SetPlane(aSh);
    }
  }
  else if (strcmp(aT,"value") == 0)
  {
    Handle(TDataStd_Constraint) C;
    if (!L.FindAttribute(TDataStd_Constraint::GetID(), C)) return 1;

    TDF_Label aLab;     
    if (!DDF::FindLabel(DF, arg[4], aLab)) return 1;
    Handle(TDataStd_Real) aR;
    if (aLab.FindAttribute(TDataStd_Real::GetID(), aR))
    {
      C->SetValue(aR);
    }
  }
  else
  {
    Handle(TDataStd_Constraint) C = TDataStd_Constraint::Set(L);

    // planar constraints
    if (strcmp(aT,"rad") == 0)             aCT = TDataStd_RADIUS;
    else if (strcmp(aT,"dia") == 0)        aCT = TDataStd_DIAMETER;
    else if (strcmp(aT,"minr") == 0)       aCT = TDataStd_MINOR_RADIUS;
    else if (strcmp(aT,"majr") == 0)       aCT = TDataStd_MAJOR_RADIUS;
    else if (strcmp(aT,"tan") == 0)        aCT = TDataStd_TANGENT;
    else if (strcmp(aT,"par") == 0)        aCT = TDataStd_PARALLEL;
    else if (strcmp(aT,"perp") == 0)       aCT = TDataStd_PERPENDICULAR;
    else if (strcmp(aT,"concentric") == 0) aCT = TDataStd_CONCENTRIC;
    else if (strcmp(aT,"equal") == 0)      aCT = TDataStd_COINCIDENT;
    else if (strcmp(aT,"dist") == 0)       aCT = TDataStd_DISTANCE;
    else if (strcmp(aT,"angle") == 0)      aCT = TDataStd_ANGLE;
    else if (strcmp(aT,"eqrad") == 0)      aCT = TDataStd_EQUAL_RADIUS;
    else if (strcmp(aT,"symm") == 0)       aCT = TDataStd_SYMMETRY;
    else if (strcmp(aT,"midp") == 0)       aCT = TDataStd_MIDPOINT;
    else if (strcmp(aT,"eqdist") == 0)     aCT = TDataStd_EQUAL_DISTANCE;
    else if (strcmp(aT,"fix") == 0)        aCT = TDataStd_FIX;
    else if (strcmp(aT,"rigid") == 0)      aCT = TDataStd_RIGID;
    // placement constraints
    else if (strcmp(aT,"from") == 0)   aCT = TDataStd_FROM;
    else if (strcmp(aT,"axis") == 0)   aCT = TDataStd_AXIS;
    else if (strcmp(aT,"mate") == 0)   aCT = TDataStd_MATE;
    else if (strcmp(aT,"alignf") == 0) aCT = TDataStd_ALIGN_FACES;
    else if (strcmp(aT,"aligna") == 0) aCT = TDataStd_ALIGN_AXES;
    else if (strcmp(aT,"axesa") == 0)  aCT = TDataStd_AXES_ANGLE;
    else if (strcmp(aT,"facesa") == 0) aCT = TDataStd_FACES_ANGLE;
    else if (strcmp(aT,"round") == 0)  aCT = TDataStd_ROUND;
    else if (strcmp(aT,"offset") == 0) aCT = TDataStd_OFFSET;
    else
    {
      di << "DDataStd_SetConstraint : unknown type, must be one of:" << "\n";
      di << "rad/dia/minr/majr/tan/par/perp/concentric/equal/dist/angle/eqrad/symm/midp/" << "\n";
      di << "eqdist/fix/rigid or from/axis/mate/alignf/aligna/axesa/facesa/round/offset" << "\n";
      di << "or plane/value" << "\n";
      return 1;
    }

    // set type
    C->SetType(aCT);

    // retrieve and set geometries
    Standard_Integer i = 1, nbSh = nb - 4;
    Handle(TNaming_NamedShape) aSh;
    TDF_Label aLab;     

    for (i = 1; i <= nbSh; i++)
    {
      if (!DDF::FindLabel(DF, arg[i+3], aLab)) return 1;  
      if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aSh))
      {
        C->SetGeometry(i, aSh);
      }
    }
  }
  return 0;
}

//=======================================================================
//function : DDataStd_GetConstraint
//purpose  : GetConstraints (document, label)
//=======================================================================
static Standard_Integer DDataStd_GetConstraint (Draw_Interpretor& di,
                                                Standard_Integer nb, 
                                                char** arg)
{
  Handle(TDataStd_Constraint) CTR;
  if (nb == 3)
  {   
    Handle(TDF_Data) DF;
    TDF_Label L;     
    if (!DDF::GetDF(arg[1],DF)) return 1;
    if (!DDF::FindLabel(DF,arg[2],L)) return 1;  
    if (L.FindAttribute(TDataStd_Constraint::GetID(),CTR))
    {
      Standard_SStream aStream;
      DDataStd::DumpConstraint (CTR,aStream);
      aStream << ends;
      di << GetSString(aStream);
    }
    else
    {
      TDF_ChildIterator it (L,Standard_True);
      for (;it.More();it.Next())
      {
        const TDF_Label& current = it.Value();
        if (current.FindAttribute(TDataStd_Constraint::GetID(),CTR))
        {
          Standard_SStream aStream;
          DDataStd::DumpConstraint (CTR,aStream);
          aStream << ends;
          di << GetSString(aStream);
        }
      }
    }
    return 0;
  }
  di << "DDataStd_GetConstraint : Error : not done" << "\n";
  return 1;
}

//=======================================================================
//function : DDataStd_SetPattern
//purpose  : SetPattern (DF,entry,signature,NSentry[realEntry,intEntry[,NSentry,realEntry,intEntry]])
//=======================================================================
static Standard_Integer DDataStd_SetPattern (Draw_Interpretor& di,
                                             Standard_Integer nb, 
                                             char** arg) 
{   
  if (nb < 5)
  {
    di << "usage: SetPattern (DF,entry,signature,NSentry[realEntry,intEntry[,NSentry,realEntry,intEntry]])" << "\n";
    return 1;
  }

  Handle(TDF_Data) DF;
  if (!DDF::GetDF(arg[1],DF)) return 1;

  TDF_Label L;     
  if (!DDF::FindLabel(DF,arg[2],L)) return 1;  

  Handle(TDataStd_PatternStd) aP = TDataStd_PatternStd::Set(L);

  // set signature
  Standard_Integer signature = atoi(arg[3]);
  aP->Signature(signature);

  TDF_Label aLab;     
  Handle(TNaming_NamedShape) TNS;
  Handle(TDataStd_Real) TReal;
  Handle(TDataStd_Integer) TInt;

  // set other parameters
  if (signature < 5)
  {
    if (nb < 7)
    {
      di<<"usage:"<<"\n";
      di<<"SetPattern (DF,entry,signature<=2,NSentry,realEntry,intEntry)"<<"\n";
      di<<"SetPattern (DF,entry,2<signature<5,NSentry,realEntry,intEntry,NSentry,realEntry,intEntry)"<<"\n";
      return 1;
    }

    // NSentry
    if (!DDF::FindLabel(DF, arg[4], aLab)) return 1;
    if (aLab.FindAttribute(TNaming_NamedShape::GetID(), TNS))
    {
      aP->Axis1(TNS);
    }

    // realEntry
    if (!DDF::FindLabel(DF, arg[5], aLab)) return 1;
    if (aLab.FindAttribute(TDataStd_Real::GetID(), TReal))
    {
      aP->Value1(TReal);
    }

    // intEntry
    if (!DDF::FindLabel(DF, arg[6], aLab)) return 1;
    if (aLab.FindAttribute(TDataStd_Integer::GetID(), TInt))
    {
      aP->NbInstances1(TInt);
    }

    if (signature > 2)
    {
      if (nb < 10)
      {
        di<<"usage:"<<"\n";
        di<<"SetPattern (DF,entry,2<signature<5,NSentry,realEntry,intEntry,NSentry,realEntry,intEntry)"<<"\n";
        return 1;
      }

      // NSentry
      if (!DDF::FindLabel(DF, arg[7], aLab)) return 1;
      if (aLab.FindAttribute(TNaming_NamedShape::GetID(), TNS))
      {
        aP->Axis2(TNS);
      }

      // realEntry
      if (!DDF::FindLabel(DF, arg[8], aLab)) return 1;
      if (aLab.FindAttribute(TDataStd_Real::GetID(), TReal))
      {
        aP->Value2(TReal);
      }

      // intEntry
      if (!DDF::FindLabel(DF, arg[9], aLab)) return 1;
      if (aLab.FindAttribute(TDataStd_Integer::GetID(), TInt))
      {
        aP->NbInstances2(TInt);
      }
    }
  }
  else
  {
    if (nb > 5)
    {
      di<<"usage: SetPattern (DF,entry,signature>=5,NSentry)"<<"\n";
      return 1;
    }

    if (!DDF::FindLabel(DF, arg[4], aLab)) return 1;
    if (aLab.FindAttribute(TNaming_NamedShape::GetID(), TNS))
    {
      aP->Mirror(TNS);
    }
  }

  return 0;
}

//=======================================================================
//function : DDataStd_DumpPattern
//purpose  : DumpPattern (DF, entry)
//=======================================================================
static Standard_Integer DDataStd_DumpPattern (Draw_Interpretor& di,
                                              Standard_Integer nb, 
                                              char** arg)
{
  Handle(TDataStd_PatternStd) CTR;
  if (nb == 3)
  {   
    Handle(TDF_Data) DF;
    TDF_Label L;     
    if (!DDF::GetDF(arg[1],DF)) return 1;
    if (!DDF::FindLabel(DF,arg[2],L)) return 1;  
    if (L.FindAttribute(TDataStd_PatternStd::GetID(),CTR))
    {
//      Standard_SStream aStream;
//      CTR->Dump(aStream);
//      aStream << ends;
//      di << aStream.rdbuf()->str();

      TCollection_AsciiString S;
      TDF_Tool::Entry(CTR->Label(),S); 
      di << S.ToCString() << " signature = " << CTR->Signature();

      if (!CTR->Axis1().IsNull())
      {
        TDF_Tool::Entry(CTR->Axis1()->Label(),S); 
        di << " Axis1 (" << S.ToCString() << ")";
      }

      if (!CTR->Value1().IsNull())
      {
        TDF_Tool::Entry(CTR->Value1()->Label(),S); 
        di << " Val1 (" << S.ToCString() << ")";
      }

      if (!CTR->NbInstances1().IsNull())
      {
        TDF_Tool::Entry(CTR->NbInstances1()->Label(),S); 
        di << " NbIns1 (" << S.ToCString() << ")";
      }

      if (!CTR->Axis2().IsNull())
      {
        TDF_Tool::Entry(CTR->Axis2()->Label(),S); 
        di << " Axis2 (" << S.ToCString() << ")";
      }

      if (!CTR->Value2().IsNull())
      {
        TDF_Tool::Entry(CTR->Value2()->Label(),S); 
        di << " Val2 (" << S.ToCString() << ")";
      }

      if (!CTR->NbInstances2().IsNull())
      {
        TDF_Tool::Entry(CTR->NbInstances2()->Label(),S); 
        di << " NbIns2 (" << S.ToCString() << ")";
      }

      if (!CTR->Mirror().IsNull())
      {
        TDF_Tool::Entry(CTR->Mirror()->Label(),S); 
        di << " Mirror (" << S.ToCString() << ")";
      }
    }
    else
    {
      TDF_ChildIterator it (L,Standard_True);
      for (;it.More();it.Next())
      {
        const TDF_Label& current = it.Value();
        if (current.FindAttribute(TDataStd_PatternStd::GetID(),CTR))
        {
          Standard_SStream aStream;
//          DDataStd::DumpPattern (CTR,aStream);
          CTR->Dump(aStream);
          aStream << ends;
          di << GetSString(aStream);
        }
      }
    }
    return 0;
  }
  di << "DDataStd_DumpPattern : Error : not done" << "\n";
  return 1;
}

//=======================================================================
//function : ConstraintCommands
//purpose  : 
//=======================================================================
void DDataStd::ConstraintCommands (Draw_Interpretor& theCommands)

{  
  static Standard_Boolean done = Standard_False;
  if (done) return;
  done = Standard_True;
  char* g = "DData : Standard Attribute Commands";
  
  theCommands.Add ("SetConstraint",
                   "SetConstraint (DF,entry,keyword,geometrie/value[,geometrie])",
                   __FILE__, DDataStd_SetConstraint, g);   
  
  theCommands.Add ("GetConstraint",
                   "GetConstraint (DF, entry)",
                   __FILE__, DDataStd_GetConstraint, g);
  
  theCommands.Add ("SetPattern",
                   "SetPattern (DF,entry,signature,NSentry[realEntry,intEntry[,NSentry,realEntry,intEntry]])",
                   __FILE__, DDataStd_SetPattern, g);   
  
  theCommands.Add ("DumpPattern",
                   "DumpPattern (DF, entry)",
                   __FILE__, DDataStd_DumpPattern, g);
}
