// Created by: Peter KURNEV
// Copyright (c) 1999-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 <BOPDS_CommonBlock.hxx>
#include <BOPDS_PaveBlock.hxx>
#include <Standard_Type.hxx>

IMPLEMENT_STANDARD_RTTIEXT(BOPDS_CommonBlock, Standard_Transient)

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

BOPDS_CommonBlock::BOPDS_CommonBlock()
    : myTolerance(0.0)
{
}

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

BOPDS_CommonBlock::BOPDS_CommonBlock(const Handle(NCollection_BaseAllocator)& theAllocator)
    : myPaveBlocks(theAllocator),
      myFaces(theAllocator),
      myTolerance(0.0)
{
}

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

void BOPDS_CommonBlock::AddPaveBlock(const Handle(BOPDS_PaveBlock)& aPB)
{
  if (myPaveBlocks.IsEmpty())
  {
    myPaveBlocks.Append(aPB);
    return;
  }
  //
  // Put the pave block with the minimal index of the original edge in the first place
  if (aPB->OriginalEdge() < myPaveBlocks.First()->OriginalEdge())
  {
    myPaveBlocks.Prepend(aPB);
  }
  else
  {
    myPaveBlocks.Append(aPB);
  }
}

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

void BOPDS_CommonBlock::SetPaveBlocks(const BOPDS_ListOfPaveBlock& aLPB)
{
  myPaveBlocks.Clear();
  BOPDS_ListIteratorOfListOfPaveBlock aIt(aLPB);
  for (; aIt.More(); aIt.Next())
  {
    AddPaveBlock(aIt.Value());
  }
}

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

const BOPDS_ListOfPaveBlock& BOPDS_CommonBlock::PaveBlocks() const
{
  return myPaveBlocks;
}

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

void BOPDS_CommonBlock::AddFace(const Standard_Integer aF)
{
  myFaces.Append(aF);
}

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

void BOPDS_CommonBlock::SetFaces(const TColStd_ListOfInteger& aLF)
{
  myFaces = aLF;
}

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

void BOPDS_CommonBlock::AppendFaces(TColStd_ListOfInteger& aLF)
{
  myFaces.Append(aLF);
}

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

const TColStd_ListOfInteger& BOPDS_CommonBlock::Faces() const
{
  return myFaces;
}

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

const Handle(BOPDS_PaveBlock)& BOPDS_CommonBlock::PaveBlock1() const
{
  return myPaveBlocks.First();
}

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

void BOPDS_CommonBlock::SetRealPaveBlock(const Handle(BOPDS_PaveBlock)& thePB)
{
  BOPDS_ListIteratorOfListOfPaveBlock it(myPaveBlocks);
  for (; it.More(); it.Next())
  {
    if (it.Value() == thePB)
    {
      myPaveBlocks.Prepend(thePB);
      myPaveBlocks.Remove(it);
      break;
    }
  }
}

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

Handle(BOPDS_PaveBlock)& BOPDS_CommonBlock::PaveBlockOnEdge(const Standard_Integer aIx)
{
  static Handle(BOPDS_PaveBlock) aPBs;
  //
  Standard_Integer                    aIOr;
  BOPDS_ListIteratorOfListOfPaveBlock anIt;
  //
  anIt.Initialize(myPaveBlocks);
  for (; anIt.More(); anIt.Next())
  {
    Handle(BOPDS_PaveBlock)& aPB = anIt.ChangeValue();
    aIOr                         = aPB->OriginalEdge();
    if (aIOr == aIx)
    {
      return aPB;
    }
  }
  return aPBs;
}

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

Standard_Boolean BOPDS_CommonBlock::IsPaveBlockOnFace(const Standard_Integer aIx) const
{
  Standard_Boolean                    bFound;
  Standard_Integer                    nF;
  TColStd_ListIteratorOfListOfInteger anIt;
  //
  bFound = Standard_False;
  anIt.Initialize(myFaces);
  for (; anIt.More(); anIt.Next())
  {
    nF = anIt.Value();
    if (nF == aIx)
    {
      return !bFound;
    }
  }
  return bFound;
}

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

Standard_Boolean BOPDS_CommonBlock::IsPaveBlockOnEdge(const Standard_Integer aIx) const
{
  Standard_Boolean                    bFound;
  Standard_Integer                    aIOr;
  BOPDS_ListIteratorOfListOfPaveBlock anIt;
  //
  bFound = Standard_False;
  anIt.Initialize(myPaveBlocks);
  for (; anIt.More(); anIt.Next())
  {
    const Handle(BOPDS_PaveBlock)& aPB = anIt.Value();
    aIOr                               = aPB->OriginalEdge();
    if (aIOr == aIx)
    {
      return !bFound;
    }
  }
  return bFound;
}

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

void BOPDS_CommonBlock::SetEdge(const Standard_Integer theEdge)
{
  BOPDS_ListIteratorOfListOfPaveBlock anIt;
  //
  anIt.Initialize(myPaveBlocks);
  for (; anIt.More(); anIt.Next())
  {
    Handle(BOPDS_PaveBlock)& aPB = anIt.ChangeValue();
    aPB->SetEdge(theEdge);
  }
}

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

Standard_Integer BOPDS_CommonBlock::Edge() const
{
  const Handle(BOPDS_PaveBlock)& aPB1 = myPaveBlocks.First();
  if (!aPB1.IsNull())
  {
    return aPB1->Edge();
  }
  return -1;
}

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

Standard_Boolean BOPDS_CommonBlock::Contains(const Handle(BOPDS_PaveBlock)& aPBx) const
{
  Standard_Boolean                    bFound;
  Standard_Integer                    aNb1;
  BOPDS_ListIteratorOfListOfPaveBlock anIt;
  //
  bFound = Standard_False;
  aNb1   = myPaveBlocks.Extent();
  //
  if (!aNb1)
  {
    return bFound;
  }
  //
  anIt.Initialize(myPaveBlocks);
  for (; anIt.More(); anIt.Next())
  {
    const Handle(BOPDS_PaveBlock)& aPB = anIt.Value();
    if (aPB == aPBx)
    {
      return !bFound;
    }
  }
  return bFound;
}

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

Standard_Boolean BOPDS_CommonBlock::Contains(const Standard_Integer theF) const
{
  Standard_Boolean                    bFound;
  TColStd_ListIteratorOfListOfInteger aIt;
  //
  bFound = Standard_False;
  aIt.Initialize(myFaces);
  for (; aIt.More(); aIt.Next())
  {
    if (aIt.Value() == theF)
    {
      return !bFound;
    }
  }
  return bFound;
}

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

void BOPDS_CommonBlock::Dump() const
{
  Standard_Integer                    nF;
  TColStd_ListIteratorOfListOfInteger aIt;
  BOPDS_ListIteratorOfListOfPaveBlock aItPB;
  //
  printf(" -- CB:\n");
  aItPB.Initialize(myPaveBlocks);
  for (; aItPB.More(); aItPB.Next())
  {
    const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value();
    aPB->Dump();
    printf("\n");
  }
  //
  if (myFaces.Extent())
  {
    printf(" Faces:");
    aIt.Initialize(myFaces);
    for (; aIt.More(); aIt.Next())
    {
      nF = aIt.Value();
      printf(" %d", nF);
    }
    printf("\n");
  }
}
