// Created on: 1997-11-26
// Created by: Jean Yves LEBEY
// Copyright (c) 1997-1999 Matra Datavision
// 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.

#ifdef DRAW
#include <TopOpeBRepTool_DRAW.hxx>
#include <TopOpeBRepDS_DRAW.hxx>

#include <DrawTrSurf.hxx>
#include <DBRep.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom_Line.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <BRep_TEdge.hxx>
#include <BRep_ListOfCurveRepresentation.hxx>
#include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
#include <BRep_CurveRepresentation.hxx>
#include <BRep_Tool.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <TopoDS.hxx>
#include <TopExp_Explorer.hxx>
#include <Precision.hxx>

Standard_EXPORT void FUN_draw (const TopoDS_Shape& s)
{
  char* nnn = TCollection_AsciiString("name").ToCString();
  if (s.IsNull()) std::cout<<"nullshape"<<std::endl;
  DBRep::Set(nnn,s);
}
Standard_EXPORT void FUN_draw (const gp_Pnt& p)
{
  char* nnn = TCollection_AsciiString("name").ToCString();
  DrawTrSurf::Set(nnn,p);
}
Standard_EXPORT void FUN_draw (const gp_Pnt2d& p)
{
  char* nnn = TCollection_AsciiString("name").ToCString();
  DrawTrSurf::Set(nnn,p);
}
Standard_EXPORT void FUN_draw (const Handle(Geom2d_Curve) c, const Standard_Real dpar)
{
  char* nnn = TCollection_AsciiString("c2d").ToCString();
  if (dpar <= Precision::Confusion()) {
    DrawTrSurf::Set(nnn,c);
    return;
  }
  Handle(Geom2d_TrimmedCurve) tC = new Geom2d_TrimmedCurve(c,0.,dpar);
  DrawTrSurf::Set(nnn,tC);
}

Standard_EXPORT void FUN_draw (const gp_Pnt& p, const gp_Dir& d)
{
  TCollection_AsciiString aa("dir"); FUN_tool_draw(aa,p,d);
}

Standard_EXPORT void FUN_brep_draw (const TCollection_AsciiString& aa, const gp_Pnt& p)
{  
  FUN_tool_draw(aa,p);
}

Standard_EXPORT void FUN_brep_draw (const TCollection_AsciiString& aa, const gp_Pnt& p, const gp_Dir& d)
{
  FUN_tool_draw(aa,p,d);
}
Standard_EXPORT void FUN_brep_draw (const TCollection_AsciiString& aa, const TopoDS_Shape& s)
{
  FUN_tool_draw(aa,s);
}
Standard_EXPORT void FUN_brep_draw 
(const TCollection_AsciiString& aa, const Handle(Geom_Curve)& C, const Standard_Real& f, const Standard_Real& l)
{
  FUN_tool_draw(aa,C,f,l);
}
Standard_EXPORT void FUN_brep_draw 
(const TCollection_AsciiString& aa, const Handle(Geom_Curve)& C)
{
  FUN_tool_draw(aa,C);
}

Standard_EXPORT void FUN_DrawMap
(const TopTools_DataMapOfShapeListOfShape& DataforDegenEd)
{
  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itemap(DataforDegenEd);
  for (; itemap.More(); itemap.Next()) {
    TopoDS_Shape v =itemap.Key();
    TopTools_ListIteratorOfListOfShape itoflos(itemap.Value());
    if(!itoflos.More()) continue;
    TopoDS_Shape Ec = itoflos.Value(); 
    if(!itoflos.More()) continue;
    itoflos.Next();
    TopoDS_Shape Ed =itoflos.Value();

    Standard_Boolean tr = Standard_False;
    if (tr) { FUN_draw(v); FUN_draw(Ec); FUN_draw(Ed);} 
  }
}

static Standard_Boolean FUN_hascurveonsurf(const TopoDS_Edge& edge,const TopoDS_Face& face)
{
  TopLoc_Location L;
  Handle(Geom_Surface) S = BRep_Tool::Surface(face,L);

  Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&edge.TShape());
  const BRep_ListOfCurveRepresentation& lcr = TE->Curves();
  BRep_ListIteratorOfListOfCurveRepresentation itcr(lcr);
  Standard_Boolean iscurveonS = Standard_False;

  for (;itcr.More();itcr.Next()) {
    const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
    Standard_Boolean iscurveonsurface = cr->IsCurveOnSurface();
    if (!iscurveonsurface) continue;
    iscurveonS = cr->IsCurveOnSurface(S,L);
    if (iscurveonS) break;
  }
  return iscurveonS;
}

Standard_EXPORT void FUN_draw2de (const TopoDS_Shape& ed,const TopoDS_Shape& fa)
{
  char* nnn = TCollection_AsciiString("name").ToCString();
  Standard_Real f,l;
  if (ed.IsNull()) return;
  if (fa.IsNull()) return;
  TopoDS_Edge edge = TopoDS::Edge(ed);
  TopoDS_Face face = TopoDS::Face(fa);
  Standard_Boolean hascons = FUN_hascurveonsurf(edge,face);
  if (!hascons) return;

  TopAbs_Orientation ori = edge.Orientation();
  Standard_Boolean sense = (ori == TopAbs_FORWARD)? Standard_True :Standard_False;
  Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edge, face,f,l);

  Handle(Geom2d_TrimmedCurve) tC2d = new Geom2d_TrimmedCurve(C2d,f,l,sense);
  DrawTrSurf::Set(nnn,tC2d);
} // FUN_draw2de

Standard_EXPORT void FUN_draw2d(const Standard_Real& par,const TopoDS_Edge& E,const TopoDS_Edge& Eref,const TopoDS_Face& Fref)
{
  TopAbs_Orientation oriE = E.Orientation();
  TopAbs_Orientation oriEref = Eref.Orientation();
  Standard_Boolean ErefonFref = Standard_False;
  Standard_Boolean EonFref = Standard_False;
  TopExp_Explorer ex; 
  Standard_Integer ne = 0;
  for (ex.Init(Fref,TopAbs_EDGE); ex.More(); ex.Next()) ne++;
  if (ne < 1) return;
  for (ex.Init(Fref,TopAbs_EDGE); ex.More(); ex.Next()) {
    const TopoDS_Edge ed = TopoDS::Edge(ex.Current());
    if (ed.IsSame(Eref)) {ErefonFref = Standard_True; break;}
    if (ed.IsSame(E)) {EonFref = Standard_True; break;}    
  }
  gp_Pnt2d p2d;
  if (ErefonFref || EonFref) {
    Standard_Real f,l;
    Handle(Geom2d_Curve) C2d;
    if (ErefonFref) {
      C2d = BRep_Tool::CurveOnSurface(Eref,Fref,f,l);  
      FUN_draw2de(Eref,Fref); 
    }
    if (EonFref) {
      C2d = BRep_Tool::CurveOnSurface(E,Fref,f,l); 
      FUN_draw2de(E,Fref); 
    }
    C2d->D0(par,p2d); 
  }
  else {
    Standard_Real f,l;    
    Handle(Geom_Curve) C3d = BRep_Tool::Curve(Eref,f,l);
    gp_Pnt P; C3d->D0(par,P);
    Handle(Geom_Surface) S = BRep_Tool::Surface(Fref);
    GeomAPI_ProjectPointOnSurf PonS(P, S);
    if (!PonS.Extrema().IsDone()) return;
    if (PonS.NbPoints() == 0) return; 
    Standard_Real u,v; PonS.Parameters(1,u,v);
    p2d = gp_Pnt2d(u,v); }
  
  FUN_draw(p2d);
} // FUN_draw2d

#endif
