// Created on: 2000-01-11
// Created by: Andrey BETENEV
// Copyright (c) 2000-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#include <STEPConstruct.hxx>

#include <StepBasic_ProductDefinition.hxx>
#include <StepBasic_ProductDefinitionRelationship.hxx>
#include <StepRepr_ProductDefinitionShape.hxx>
#include <StepRepr_PropertyDefinition.hxx>
#include <StepRepr_RepresentationItem.hxx>
#include <StepShape_ContextDependentShapeRepresentation.hxx>
#include <StepShape_ShapeDefinitionRepresentation.hxx>
#include <Transfer_FinderProcess.hxx>
#include <Transfer_SimpleBinderOfTransient.hxx>
#include <Transfer_TransientProcess.hxx>
#include <TransferBRep.hxx>
#include <TransferBRep_ShapeMapper.hxx>

//=================================================================================================

Handle(StepRepr_RepresentationItem) STEPConstruct::FindEntity(
  const Handle(Transfer_FinderProcess)& FinderProcess,
  const TopoDS_Shape&                   Shape)
{
  Handle(StepRepr_RepresentationItem) item;
  Handle(TransferBRep_ShapeMapper)    mapper = TransferBRep::ShapeMapper(FinderProcess, Shape);
  FinderProcess->FindTypedTransient(mapper, STANDARD_TYPE(StepRepr_RepresentationItem), item);
#ifdef OCCT_DEBUG
  if (item.IsNull())
    std::cout << Shape.TShape()->DynamicType()->Name() << ": RepItem not found" << std::endl;
  else
    std::cout << Shape.TShape()->DynamicType()->Name()
              << ": RepItem found: " << item->DynamicType()->Name() << std::endl;
#endif
  return item;
}

//=================================================================================================

Handle(StepRepr_RepresentationItem) STEPConstruct::FindEntity(
  const Handle(Transfer_FinderProcess)& FinderProcess,
  const TopoDS_Shape&                   Shape,
  TopLoc_Location&                      Loc)
{
  Handle(StepRepr_RepresentationItem) item;
  Loc                                     = Shape.Location();
  Handle(TransferBRep_ShapeMapper) mapper = TransferBRep::ShapeMapper(FinderProcess, Shape);
  if (!FinderProcess->FindTypedTransient(mapper, STANDARD_TYPE(StepRepr_RepresentationItem), item)
      && !Loc.IsIdentity())
  {
    Loc.Identity();
    TopoDS_Shape S = Shape;
    S.Location(Loc);
    mapper = TransferBRep::ShapeMapper(FinderProcess, S);
    FinderProcess->FindTypedTransient(mapper, STANDARD_TYPE(StepRepr_RepresentationItem), item);
  }
#ifdef OCCT_DEBUG
  if (item.IsNull())
    std::cout << Shape.TShape()->DynamicType()->Name() << ": RepItem not found" << std::endl;
  else if (Loc != Shape.Location())
    std::cout << Shape.TShape()->DynamicType()->Name()
              << ": RepItem found for shape without location: " << item->DynamicType()->Name()
              << std::endl;
  else
    std::cout << Shape.TShape()->DynamicType()->Name()
              << ": RepItem found: " << item->DynamicType()->Name() << std::endl;
#endif
  return item;
}

//=================================================================================================

TopoDS_Shape STEPConstruct::FindShape(const Handle(Transfer_TransientProcess)&   TransientProcess,
                                      const Handle(StepRepr_RepresentationItem)& item)
{
  TopoDS_Shape            S;
  Handle(Transfer_Binder) binder = TransientProcess->Find(item);
  if (!binder.IsNull() && binder->HasResult())
  {
    S = TransferBRep::ShapeResult(TransientProcess, binder);
  }
  return S;
}

//=================================================================================================

Standard_Boolean STEPConstruct::FindCDSR(
  const Handle(Transfer_Binder)&                         ComponentBinder,
  const Handle(StepShape_ShapeDefinitionRepresentation)& AssemblySDR,
  Handle(StepShape_ContextDependentShapeRepresentation)& ComponentCDSR)
{
  Standard_Boolean result = Standard_False;

  Handle(StepRepr_PropertyDefinition) PropD = AssemblySDR->Definition().PropertyDefinition();
  if (!PropD.IsNull())
  {
    Handle(StepBasic_ProductDefinition) AssemblyPD = PropD->Definition().ProductDefinition();
    if (!AssemblyPD.IsNull())
    {
      Handle(Transfer_Binder)                         binder = ComponentBinder;
      Handle(Transfer_SimpleBinderOfTransient)        trb;
      Handle(StepRepr_ProductDefinitionShape)         PDS;
      Handle(StepBasic_ProductDefinitionRelationship) NAUO;
      Handle(StepBasic_ProductDefinition)             ComponentPD;
      while (!binder.IsNull() && !result)
      {
        trb = Handle(Transfer_SimpleBinderOfTransient)::DownCast(binder);
        if (!trb.IsNull())
        {
          ComponentCDSR =
            Handle(StepShape_ContextDependentShapeRepresentation)::DownCast(trb->Result());
          if (!ComponentCDSR.IsNull())
          {
            PDS = ComponentCDSR->RepresentedProductRelation();
            if (!PDS.IsNull())
            {
              NAUO = PDS->Definition().ProductDefinitionRelationship();
              if (!NAUO.IsNull())
              {
                ComponentPD = NAUO->RelatingProductDefinition();
                result      = (ComponentPD == AssemblyPD);
              }
            }
          }
        }
        binder = binder->NextResult();
      }
    }
  }
  return result;
}
