#include <XSControl_TransferWriter.ixx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <Transfer_SimpleBinderOfTransient.hxx>
#include <Transfer_TransientMapper.hxx>
#include <XSControl_Utils.hxx>

#include <Interface_TraceFile.hxx>
#include <Interface_Macros.hxx>
#include <Interface_Check.hxx>


    XSControl_TransferWriter::XSControl_TransferWriter ()
{  theTransferWrite = new Transfer_FinderProcess;  theTransferMode = 0;  }

    Handle(Transfer_FinderProcess)  XSControl_TransferWriter::FinderProcess () const
      {  return theTransferWrite;  }

    void  XSControl_TransferWriter::SetFinderProcess (const Handle(Transfer_FinderProcess)& FP)
      {  theTransferWrite = FP;  }

    Handle(XSControl_Controller)  XSControl_TransferWriter::Controller () const
      {  return theController;  }

    void  XSControl_TransferWriter::SetController (const Handle(XSControl_Controller)& ctl)
{
  theController = ctl;
  Clear(-1);
}

    void  XSControl_TransferWriter::Clear (const Standard_Integer mode)
{
  if (mode < 0 || theTransferWrite.IsNull())
    theTransferWrite = new Transfer_FinderProcess;
  else theTransferWrite->Clear();
}

    Standard_Integer  XSControl_TransferWriter::TransferMode () const
      {  return theTransferMode;  }

    void  XSControl_TransferWriter::SetTransferMode (const Standard_Integer mod)
      {  theTransferMode = mod;  }

    void  XSControl_TransferWriter::PrintStats
  (const Standard_Integer , const Standard_Integer ) const
{
  Standard_OStream& sout = Interface_TraceFile::Def();
//  A ameliorer ... !
    sout<<"\n*******************************************************************\n";
    sout << "******        Statistics on Transfer (Write)                 ******"<<endl;
    sout<<"\n*******************************************************************\n";
    sout << "******        Transfer Mode = "<<theTransferMode;
    Standard_CString modehelp = theController->ModeWriteHelp (theTransferMode);
    if (modehelp && modehelp[0] != 0) sout<<"  I.E.  "<<modehelp;
    sout<<"       ******"<<endl;
}


//  ##########    LES ACTIONS    ##########

    Standard_Boolean  XSControl_TransferWriter::RecognizeTransient
  (const Handle(Standard_Transient)& obj)
{
  if (theController.IsNull()) return Standard_False;
  XSControl_Utils xu;
  TopoDS_Shape sh = xu.BinderShape (obj);
  if (!sh.IsNull()) return RecognizeShape (sh);
  return theController->RecognizeWriteTransient (obj,theTransferMode);
}

    IFSelect_ReturnStatus  XSControl_TransferWriter::TransferWriteTransient
  (const Handle(Interface_InterfaceModel)& model,
   const Handle(Standard_Transient)& obj)
{
  IFSelect_ReturnStatus status = IFSelect_RetVoid;
  if (theController.IsNull()) return IFSelect_RetError;
  if (model.IsNull()) return IFSelect_RetVoid;

  if (theTransferWrite.IsNull()) theTransferWrite = new Transfer_FinderProcess;
  Handle(Transfer_ActorOfFinderProcess) nulact;
  theTransferWrite->SetActor (nulact);
  Handle(Standard_Transient) resultat;
  try {
    OCC_CATCH_SIGNALS
    if (Interface_TraceFile::DefLevel() > 0) {
      PrintStats(theTransferMode);
      Standard_OStream& sout = Interface_TraceFile::Def();
      sout << "******        Transferring Transient, CDL Type = ";
      sout<<obj->DynamicType()->Name()<<"   ******"<<endl;
    }
    status = theController->TransferWriteTransient
      (obj,theTransferWrite,model,theTransferMode);
  }
  catch(Standard_Failure) {
    Standard_OStream& sout = Interface_TraceFile::Def();
    Handle(Standard_Failure) afail = Standard_Failure::Caught();
    sout<<"****  ****  TransferWriteShape, EXCEPTION : "; afail->Print(sout); sout<<endl;
    status = IFSelect_RetFail;
  }
  return status;
}


    Standard_Boolean  XSControl_TransferWriter::RecognizeShape
  (const TopoDS_Shape& shape)
{
  if (theController.IsNull()) return Standard_False;
  if (shape.IsNull()) return Standard_False;
  return theController->RecognizeWriteShape (shape,theTransferMode);
}


    IFSelect_ReturnStatus  XSControl_TransferWriter::TransferWriteShape
  (const Handle(Interface_InterfaceModel)& model,
   const TopoDS_Shape& shape)
{
  IFSelect_ReturnStatus status = IFSelect_RetVoid;
  if (theController.IsNull()) return IFSelect_RetError;
  if (model.IsNull()) return IFSelect_RetVoid;

  if (theTransferWrite.IsNull()) theTransferWrite = new Transfer_FinderProcess;
//  effacer l actor : Controller s en charge
  Handle(Transfer_ActorOfFinderProcess) nulact;
  theTransferWrite->SetActor (nulact);
  Handle(Standard_Transient) resultat;
  try {
    OCC_CATCH_SIGNALS
    if (Interface_TraceFile::DefLevel() > 0) {
      PrintStats(theTransferMode);
      Standard_OStream& sout = Interface_TraceFile::Def();
      sout << "******        Transferring Shape, ShapeType = ";
      TopAbs::Print (shape.ShapeType(),sout);
      sout<<"                      ******"<<endl;
    }
    status = theController->TransferWriteShape
      (shape,theTransferWrite,model,theTransferMode);
  }
  catch(Standard_Failure) {
    Standard_OStream& sout = Interface_TraceFile::Def();
    Handle(Standard_Failure) afail = Standard_Failure::Caught();
    sout<<"****  ****  TransferWriteShape, EXCEPTION : "; afail->Print(sout); sout<<endl;
    status = IFSelect_RetFail;
  }
  return status;
}


    Interface_CheckIterator  XSControl_TransferWriter::CheckList () const
{
  Interface_CheckIterator  chl;
  if (theTransferWrite.IsNull()) return chl;
  Standard_Integer i, nb = theTransferWrite->NbMapped();
  for (i = 1; i <= nb; i ++) {
    DeclareAndCast(Transfer_SimpleBinderOfTransient,tb,theTransferWrite->MapItem
(i));
    if (tb.IsNull()) continue;
    Handle(Interface_Check) ach = tb->Check();
    if (ach->NbFails() == 0 || ach->NbWarnings() == 0) continue;
    DeclareAndCast(Transfer_TransientMapper,tm,theTransferWrite->Mapped(i));
    if (tm.IsNull()) ach->GetEntity (theTransferWrite->Mapped(i));
    else  ach->GetEntity (tm->Value());
    chl.Add(ach);
  }
  return chl;
}

    Interface_CheckIterator  XSControl_TransferWriter::ResultCheckList
  (const Handle(Interface_InterfaceModel)& model) const
{
  Interface_CheckIterator  chl;
  if (theTransferWrite.IsNull()) return chl;
  Standard_Integer i, nb = theTransferWrite->NbMapped();
  for (i = 1; i <= nb; i ++) {
    DeclareAndCast(Transfer_SimpleBinderOfTransient,tb,theTransferWrite->MapItem
(i));
    if (tb.IsNull()) continue;
    const Handle(Interface_Check) ach = tb->Check();
    if (ach->NbFails() == 0 || ach->NbWarnings() == 0) continue;
    Handle(Standard_Transient) ent = tb->Result();
    if (!ent.IsNull() && !model.IsNull()) chl.Add(ach,model->Number(ent));
    else  chl.Add(ach,0);
  }
  return chl;
}

    void  XSControl_TransferWriter::PrintStatsProcess
  (const Handle(Transfer_FinderProcess)& ,
   const Standard_Integer , const Standard_Integer )
{  }
