#ifndef __DETAILSYM_H
#define __DETAILSYM_H
//
//  (C) Copyright 1993-2008 by Autodesk, Inc.  All rights reserved.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted, 
// provided that the above copyright notice appears in all copies and 
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting 
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC. 
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to 
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//

#ifndef __ACMDEF_H
	#error include 'acmdef.h' before including this file
#endif
#ifndef __CAUXENT_H
	#error include 'cauxent.h' before including this file
#endif

class AcDbIdPair;
class AcmSymbolStd;
class AmdtDetailSymC;
class AmdtDetailSymCImp;
class AmdtDetailSymEntImp;
class AcmCAttach;
class AcmStringValue;
class AcmBooleanValue;
class AmdtDetailSymStdImp;

class DllImpExp AmdtDetailSymStd : public AcmSymbolStd
{
  friend class AcmSymbbInternals;
  friend class AmdtDetailSymStdImp;
public:
  ACRX_DECLARE_MEMBERS(AmdtDetailSymStd);

  virtual ~AmdtDetailSymStd();

  void nextDetailNames(CStringArray& names, const int count) const;
  virtual CString defaultName(int count) const;

  Adesk::Boolean showBorder() const;
  void setShowBorder(const Adesk::Boolean val);

  Adesk::Boolean showLeader() const;
  void setShowLeader(const Adesk::Boolean val);

  Adesk::Boolean showAnnotLeader() const;
  void setShowAnnotLeader(const Adesk::Boolean val);

  const ACHAR* labelPattern() const;
  void setLabelPattern(const ACHAR* labelPattern);

  Adesk::Boolean labelAbove() const;
  void setLabelAbove(const Adesk::Boolean p);

  AcDbObjectId annotLineId() const;
  void setAnnotLineId(const AcDbObjectId& idType);

  LPCTSTR getAnnotLtypeName() const;
  Acad::ErrorStatus setAnnotLtypeName(LPCTSTR pName);

  virtual void setTextHeightByStandard(bool byStandard);
  virtual void setTextColorByStandard(bool byStandard);

  virtual double byStdTextHeight() const;
  virtual const AcCmColor & byStdTextTrueColor() const;

  Adesk::UInt16     textColor() const;
  void              setTextColor(Adesk::UInt16 color);  

  AcDbObjectId textStyleId() const;
  void setTextStyleId(const AcDbObjectId& id);

  bool textStyleByStandard() const;
  void setTextStyleByStandard(bool byStandard);

  AcArray<double> allowedScales() const;
  void setAllowedScales(const AcArray<double>& scales);
  void addAllowedScale(const double& scale);
  void eraseAllowedScales();
  double nearestAllowedScale(const double& scale);

  virtual void initToEdit();
  virtual void initToEditOriginal();

  virtual Adesk::Boolean setFactoryDefaults();
  virtual Acm::ErrorStatus onChangeUnits(Adesk::Boolean isMetric);
  virtual Acm::ErrorStatus getDescription(CString& desc,
                                          CBitmap*& pBmpLoaded,
                                          CBitmap*& pBmpReg,
                                          Adesk::Boolean& enablePref) const;

  // gets subents from source geometry
  // for detail annotation
  virtual void getSubEntsSourceGeom(const AmdtDetailSymC* pSymb,AcmCAuxEntArray& subents) const;
  virtual void getSubEntsText(const AmdtDetailSymC* pSymb,AcmCAuxEntArray& subents) const;
  virtual void getSubEntsLeader(const AmdtDetailSymC* pSymb,AcmCAuxEntArray& subents,
                                AcGePoint3d* labelOri = NULL) const;
  // for detail view border
  virtual void getSubEntsEntSourceGeom(const AmdtDetailSymC* pSymb,AcmCAuxEntArray& subents) const;
  virtual void getSubEntsEntText(const AmdtDetailSymC* pSymb,AcmCAuxEntArray& subents) const;

  virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
  virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;

  enum Variable {
    kLabelPattern = 0,
    kShowBorder,
    kShowLeader,
    kShowAnnotLeader,
    kLabelAbove,
    kArrowHead
  };

  virtual Acm::Visibility variableStatus(AmdtDetailSymStd::Variable var) const;
  virtual void setVariableStatus(AmdtDetailSymStd::Variable var, Acm::Visibility status);

  virtual bool isHeightSizedUp() const;

protected:
  AmdtDetailSymStd();
  virtual Acad::ErrorStatus createDefaultLTypeAnnotLine(LPCTSTR pName);

   bool isIntersectLineWithCurve (const AcGePoint3d& pnt1,
                                  const AcGePoint3d& pnt2,
                                  const AcDbCurve* pCurve,
                                  AcGePoint3d* intersectPnt = NULL) const;

   AcGePoint3d getIntersectPoint (const AcGePoint3d& pnt1,
                                  const AcGePoint3d& pnt2,
                                  const AcDbCurve* pCurve) const;

  virtual Acad::ErrorStatus subGetClassID(CLSID* pClsid) const;

private:
  AmdtDetailSymStdImp* mpImp;
};
MAKE_ACDBOPENOBJECT_FUNCTION(AmdtDetailSymStd);
DBREF_DECLARE(AmdtDetailSymStd)


class DllImpExp AmdtDetailSym : public AcmSymbol
{
public:
  ACRX_DECLARE_MEMBERS(AmdtDetailSym);
  AmdtDetailSym(const AcGePoint3d& origin = AcGePoint3d::kOrigin,
                const double detailScale = 1.0,
                const AcDbObjectId& baseViewId = NULL);

  virtual ~AmdtDetailSym();             

  AcDbObjectId detailViewId() const;
  AcDbObjectId baseViewId() const;

  virtual AcGePoint3d origin() const;
  virtual void setOrigin(const AcGePoint3d& origin);
  void setOrigin(const AcGePoint3d& origin, bool bModifySourceGeom);

  double detailScale() const;
  void setDetailScale(const double scale);

  double correctionScaleFactor() const;
  void setCorrectionScaleFactor(const double corr);

  double baseViewScale() const;
  void setBaseViewScale(const double scale);

  AcGeVector3d annotOffset() const;
  void setAnnotOffset(const AcGeVector3d& offset);

  // these two are here for setting the text offset in AmdtDetailSymLabel
  AcGeVector3d labelEntOffset () const;
  void setLabelEntOffset (const AcGeVector3d& offset);
  
  double radius() const;
  void setRadius(double radius);
  void setRadius(double radius, bool bModifySourceGeom);

  AcDbObjectId labelEntId () const;
  void setLabelEntId (const AcDbObjectId& id);

  AcGePoint3dArray leaderPoints() const;
  void setLeaderPoints(const AcGePoint3dArray& leaderPoints);
  void addLeaderPoint(const AcGePoint3d& point);
  void eraseLeaderPoints();

  const ACHAR* labelName() const;
  void setLabelName(const ACHAR* labelName);

  const ACHAR* labelPattern() const;
  void setLabelPattern(const ACHAR* labelPattern);

  // returns the evaluated pattern (with label name and scale)
  CString labelText() const;

  bool isShowBorder() const;
  void setShowBorder( bool bVal);

  bool isShowLeader() const;
  void setShowLeader( bool bVal);

  bool isShowAnnotLeader() const;
  void setShowAnnotLeader( bool bVal);

  // this one is for AmdtDetailSym, we have to be able to change the geometry (in transformBy)
  AcDbCurve* sourceGeom() const;

  LPCTSTR value(Acm::Variable var) const;
  Acm::ErrorStatus setValue(Acm::Variable var, LPCTSTR value);

  Acm::Visibility  variableStatus(Acm::Variable var) const;
  Acm::ErrorStatus setVariableStatus(Acm::Variable var, Acm::Visibility status);

  Acm::ErrorStatus getVarDlgInfo(Acm::Variable var,CVarDlgInfo& v) const;
  Acm::ErrorStatus setVarDlgInfo(Acm::Variable var,const CVarDlgInfo& v);

  virtual Acm::ErrorStatus setSymbolDefaults(AcDbDatabase* pDb = NULL);

  virtual AmdtDetailSymC* subSymbol() const;

  using AcmSymbol::transformBy;
  virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform,
                                        double symbolScale);

  virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
  virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;
  
  virtual Acad::ErrorStatus subErase (Adesk::Boolean pErasing);

  // create an AmdtDetailSymLabel object
  Acad::ErrorStatus makeLabelEnt (const AcGePoint3d& origin,
                                   const AcDbObjectId& detailViewId,  
                                   const AcDbObjectId& entOwnerId = NULL,
                                   bool bCreateCopyLabel = false,
                                   bool bUseCorrectionScale = false);

  // prepare mSourceGeom from an existing geometry
  Acad::ErrorStatus makeSourceGeom(AcDbCurve* pSourceGeom);
  // create circle source geom
  Acad::ErrorStatus makeSourceGeom(const AcGePoint3d& center, 
                                   const AcGeVector3d& normal, 
                                   const double radius);
  // create ellipse source geom
  Acad::ErrorStatus makeSourceGeom(const AcGePoint3d& center,
                                   const AcGeVector3d& normal,
                                   const AcGeVector3d& majorAxis,
                                   double radiusRatio);

   bool isSpecByAbsScale () const;
   void setIsSpecByAbsScale (bool bVal);

   int detailSpace () const;
   void setDetailSpace (int space);

   bool isAssocDetail () const;
   void setIsAssocDetail (bool bVal);

   AcDbObjectId copyLabelEntId () const;
   void setCopyLabelEntId (const AcDbObjectId& id);

   AcGeVector3d copyLabelEntOffset () const;
   void setCopyLabelEntOffset (const AcGeVector3d& offset);
   
   Acad::ErrorStatus acmDeepClone (const AcDbObjectId& sourceId,
                                   AcDbObject* pOwner,
                                   AcDbIdMapping& idMap,
                                   Adesk::Boolean isPrimary) const;

   Acad::ErrorStatus acmWblockClone (const AcDbObjectId& sourceId,
                                     AcRxObject* pOwner,
                                     AcDbIdMapping& idMap,
                                     Adesk::Boolean isPrimary) const;

   bool isValidCopyLabelEnt () const;

   bool isCreatedOrEdited () const;
   void setIsCreatedOrEdited (bool bVal);

   Acad::ErrorStatus transformBy (const AcGeMatrix3d& xform, double symbolScale, bool b2dStructTransform);

   virtual Acm::ErrorStatus addLeader(const AcGePoint3dArray &ptrArray);
   virtual Acm::ErrorStatus removeLeader(Adesk::UInt16 index);

protected:
  virtual Adesk::Boolean    subWorldDraw(AcGiWorldDraw* mode);
  virtual void              subViewportDraw(AcGiViewportDraw* mode);
  
  virtual Acad::ErrorStatus subGetGripPoints(AcGePoint3dArray&,
                                          AcDbIntArray&,
                                          AcDbIntArray&) const;

  virtual Acad::ErrorStatus   subGetGripPoints(AcDbGripDataPtrArray& grips,
														  const double curViewUnitSize, 
														  const int gripSize, 
													     const AcGeVector3d& curViewDir, 
														  const int bitflags) const;

  virtual Acad::ErrorStatus subMoveGripPointsAt(const AcDbIntArray& indices,
                                             const AcGeVector3d& offset); 

  virtual Acad::ErrorStatus subExplode(AcDbVoidPtrArray& entitySet) const;

  virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d& xform);

  virtual Acad::ErrorStatus subGetClassID(CLSID* pClsid) const;

  virtual Acad::ErrorStatus subDeepClone(AcDbObject* pOwner, 
                                      AcDbObject*& pClonedObject,
                                      AcDbIdMapping& idMap, 
                                      Adesk::Boolean isPrimary = Adesk::kTrue) const;
  virtual Acad::ErrorStatus subWblockClone(AcRxObject* pOwner, 
                                      AcDbObject*& pClonedObject,
                                      AcDbIdMapping& idMap, 
                                      Adesk::Boolean isPrimary = Adesk::kTrue) const;

  virtual Acad::ErrorStatus subGetGeomExtents(AcDbExtents& extents) const;

  // used when source geom is resized to keep texts in their desired relative position
  void updateAnnotOffsets (const double scale);
  void updateDetail2d (const AcGeMatrix3d& xform);

  AmdtDetailSymCImp* mpSubSymbol;
};    
MAKE_ACDBOPENOBJECT_FUNCTION(AmdtDetailSym);
DBREF_DECLARE(AmdtDetailSym);


class DllImpExp AmdtDetailSymLabel : public AcmSymbol
{
  friend class AcmSymbbInternals;
public:
  ACRX_DECLARE_MEMBERS(AmdtDetailSymLabel);
  AmdtDetailSymLabel(const AcGePoint3d& origin = AcGePoint3d::kOrigin,
                   const AcDbObjectId& detailViewId = NULL);
  virtual ~AmdtDetailSymLabel();

  //AcDbEntity and AcDbCurve overrides
  virtual Acad::ErrorStatus getStartParam(double& startParam) const;
  virtual Acad::ErrorStatus getEndParam(double& endParam) const;
  virtual Acad::ErrorStatus getPointAtParam(double param,AcGePoint3d& point) const;
  virtual Acad::ErrorStatus getArea(double& area) const;


  virtual AcGePoint3d origin() const;
  virtual void setOrigin(const AcGePoint3d& origin);

  AcGeVector3d annotOffset() const;
  void setAnnotOffset(const AcGeVector3d& vect);
  // used when source geom or detail view scale are changed
  void updateAnnotOffset(const double scale);

  AcDbObjectId symbolEntId () const;
  void setSymbolEntId (const AcDbObjectId& id);

  void highlightAll();
  void unhighlightAll();

  using AcmSymbol::transformBy;
  virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform,
                                        double symbolScale);

  virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
  virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;

  virtual Acad::ErrorStatus subErase(Adesk::Boolean pErasing);

  virtual Acm::ErrorStatus setSymbolDefaults(AcDbDatabase* pDatabase = NULL);
  virtual void regen();

   void getSubEntsText (const AmdtDetailSymStd* pStd, AcmCAuxEntArray& subents) const;
   CString labelText   () const;
   bool isAssocDetail () const;

   Acad::ErrorStatus acmDeepClone (const AcDbObjectId& sourceId,
                                   AcDbObject* pOwner,
                                   AcDbIdMapping& idMap,
                                   Adesk::Boolean isPrimary) const;

   Acad::ErrorStatus acmWblockClone (const AcDbObjectId& sourceId,
                                     AcRxObject* pOwner,
                                     AcDbIdMapping& idMap,
                                     Adesk::Boolean isPrimary) const;

   void setTextGeomExtents (bool bValue);

   Adesk::Boolean labelAbove() const;
   void setLabelAbove (Adesk::Boolean);

   virtual Acm::ErrorStatus addLeader(const AcGePoint3dArray &ptrArray);
   virtual Acm::ErrorStatus removeLeader(Adesk::UInt16 index);

protected:   
  virtual Adesk::Boolean    subWorldDraw(AcGiWorldDraw* mode);

  double getCalculatedGeomScale (const AmdtDetailSym* pSym) const;
  
  virtual Acad::ErrorStatus subIntersectWith(const AcDbEntity* pEnt,AcDb::Intersect intType,
                            AcGePoint3dArray& points,INT_PTR thisGsMarker = 0,INT_PTR otherGsMarker= 0) const;
  virtual Acad::ErrorStatus subGetGeomExtents(AcDbExtents& extents) const;
  
  virtual Acad::ErrorStatus subGetGripPoints(AcGePoint3dArray&,
                                          AcDbIntArray&,
                                          AcDbIntArray&) const;

  virtual Acad::ErrorStatus	subGetGripPoints(AcDbGripDataPtrArray& grips,
                                            const double curViewUnitSize, 
                                            const int gripSize, 
                                            const AcGeVector3d& curViewDir, 
                                            const int bitflags) const;

  virtual Acad::ErrorStatus subMoveGripPointsAt(const AcDbIntArray& indices,
                                             const AcGeVector3d& offset); 

  virtual Acad::ErrorStatus subExplode(AcDbVoidPtrArray& entitySet) const;

  virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d& xform);
  
  virtual Acad::ErrorStatus subGetClassID(CLSID* pClsid) const;

  virtual Acad::ErrorStatus subDeepClone(AcDbObject* pOwner, 
                                      AcDbObject*& pClonedObject,
                                      AcDbIdMapping& idMap, 
                                      Adesk::Boolean isPrimary = Adesk::kTrue) const;
  virtual Acad::ErrorStatus subWblockClone(AcRxObject* pOwner, 
                                      AcDbObject*& pClonedObject,
                                      AcDbIdMapping& idMap, 
                                      Adesk::Boolean isPrimary = Adesk::kTrue) const;

protected:
   AmdtDetailSymEntImp* mpSubSymbol;
   int mConvert;
   bool mbGetTextGeomExtents;
};
MAKE_ACDBOPENOBJECT_FUNCTION(AmdtDetailSymLabel);
DBREF_DECLARE(AmdtDetailSymLabel)

/////////////////////////////////////////////////////////////////////
// DETAIL LABEL SYMBOL OLD CLASS
// this is the dummy class to enable us to convert from older dwgs
/////////////////////////////////////////////////////////////////////

class DllImpExp AmdtDetailSymEnt : public AcDbCurve
{
public:
  ACRX_DECLARE_MEMBERS(AmdtDetailSymEnt);
  static void rxInit2();

  virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
  virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;

protected:
  void *operator new[](size_t nSize) { UNREFERENCED_PARAMETER(nSize);assert(0); return NULL; }
  void operator delete[](void *p) { UNREFERENCED_PARAMETER(p);assert(0); }
};    

/////////////////////////////////////////////////////////////////////
// DETAIL MAIN SYMBOL C-CLASS
/////////////////////////////////////////////////////////////////////

class AmdtDetailSymC : public AcmCSubSymbol
{
public:
  virtual const AcDbCurve* sourceGeometry() const = 0;

  virtual AcGeVector3d annotOffset() const = 0;
  virtual void setAnnotOffset(const AcGeVector3d& offset) = 0;

  virtual AcGeVector3d labelEntOffset() const = 0;
  virtual void setLabelEntOffset(const AcGeVector3d& offset) = 0;

  virtual double radius() const = 0;
  virtual void setRadius(const double radius) = 0;

  virtual double detailScale() const = 0;
  virtual void setDetailScale(const double scale) = 0;

  virtual double correctionScaleFactor() const = 0;
  virtual void setCorrectionScaleFactor(const double scale) = 0;

  virtual double baseViewScale() const = 0;
  virtual void setBaseViewScale(const double scale) = 0;

  virtual const ACHAR* labelName() const = 0;
  virtual void setLabelName(const ACHAR* labelName) = 0;

  virtual const ACHAR* labelPattern() const = 0;
  virtual void setLabelPattern(const ACHAR* labelPattern) = 0;

  virtual CString labelText() const = 0;

  virtual Adesk::Boolean isShowBorder() const = 0;
  virtual void setShowBorder(const Adesk::Boolean v) = 0;

  virtual Adesk::Boolean isShowLeader() const = 0;
  virtual void setShowLeader(const Adesk::Boolean v) = 0;

  virtual Adesk::Boolean isShowAnnotLeader() const = 0;
  virtual void setShowAnnotLeader(const Adesk::Boolean v) = 0;

  virtual AcGePoint3dArray leaderPoints() const = 0;
  virtual void setLeaderPoints(const AcGePoint3dArray& leaderPoints) = 0;
  virtual void addLeaderPoint(const AcGePoint3d& point) = 0;
  virtual void eraseLeaderPoints() = 0;

  //some recals to AcmSymbol needed for getSubEnts in AmdtDetailSymStd
  virtual double scale() const = 0;
  virtual AcGeVector3d normal() const = 0;
  virtual AcGeVector3d xDir() const = 0;
  virtual AcGeVector3d yDir() const = 0;

  virtual AcDbObjectId labelEntId() const = 0;
  
  virtual int  detailSpace () const = 0;
  virtual void setDetailSpace (int space) = 0;
};

#endif // __DETAILSYM_H
