//////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2025 by Autodesk, Inc.  All rights reserved.
//
// This computer source code and related instructions and comments 
// are the unpublished confidential and proprietary information of 
// Autodesk, Inc. and are protected under applicable copyright and 
// trade secret law.  They may not be disclosed to, copied or used 
// by any third party without the prior written consent of Autodesk, Inc.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __DETAILSYM_H
#define __DETAILSYM_H
#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 AcDbDetailViewStyle;
class AmdtDetailSymStdLegacyImp;


///<summary>This is class AmdtDetailSymStd.</summary>
class ACMSYMBB_CRX_DLLSHARE AmdtDetailSymStd : public AcmSymbolStd
{
  friend class AcmSymbbInternals;
  friend class AmdtDetailSymStdImp;
  friend class AmdtDetailSymStdLegacyImp;
  friend class AmdtDetailStdPreKastlePostRestore1;
  friend class AmdtDetailStdPreKastlePostRestore2;
public:
  ACRX_DECLARE_MEMBERS(AmdtDetailSymStd);
  virtual ~AmdtDetailSymStd();
  
  void nextDetailNames(CStringArray& names, const int count) const;
  virtual CString defaultName(int count) const;
  const ACHAR* getBaseSymStdClassName() const override;
  //////////////////////////////////////////////////////////////////////////
  // Symbol auto-incrementing label name interface overrides 
  Acm::ErrorStatus getDefaultName(AcString& name, int& count) const override;
  Adesk::Boolean isSymbolCounterSupported() const override;
  //////////////////////////////////////////////////////////////////////////
  
  Adesk::Boolean showBorder() const;
  void setShowBorder(const Adesk::Boolean val);

  Adesk::Boolean showConnectionLine() const;
  void setShowConnectionLine(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);

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

  Adesk::UInt16     textColor() const;
  void              setTextColor(Adesk::UInt16 color);  
  
  AcDbObjectId textStyleId() const;
  void setTextStyleId(const AcDbObjectId& id);
  
  ///<summary>Retrieves the by standard state for the corresponding property.</summary>
  bool textStyleByStandard() const;
  ///<summary>Sets the by standard state for the corresponding property.</summary>
  ///<param name="byStandard">New state to set to.</param>
  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);
  
  void initToEdit()const override;
  void initToEditOriginal()const override;

  /// <summary>
  /// Sets the factory default values. This function will create associated AcDbDetailViewStyle if it is not created yet.
  /// DO NOT override this function.
  /// </summary>
  virtual Adesk::Boolean setFactoryDefaults();

  /// <summary>
  /// Sets the factory default values for the properties in the associated AcDbDetailViewStyle. 
  /// You should override this function for different default values.
  /// </summary>
  ///
  /// <returns>
  /// Return Adesk::kTrue if successful.
  /// </returns>
  virtual Adesk::Boolean subSetFactoryDefaults();

  ///<summary>This member function is called on all symbol standards when their owner, the AcmStandard
  ///object, changes units from millimeters to inches or vice versa.</summary>
  virtual Acm::ErrorStatus onChangeUnits(Adesk::Boolean isMetric);
  virtual Acm::ErrorStatus getDescription(CString& desc,
                                          CBitmap*& pBmpLoaded,
                                          CBitmap*& pBmpReg,
                                          Adesk::Boolean& enablePref) const;

  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;
  virtual void getSubEntsEntSourceGeom(const AmdtDetailSymC* pSymb,AcmCAuxEntArray& subents) const;
  virtual void getSubEntsEntText(const AmdtDetailSymC* pSymb,AcmCAuxEntArray& subents) const;

  /// <summary>
  /// Indicates whether properties in the associated AcDbDetailViewStyle are changed.
  /// </summary>
  ///
  /// <returns>
  /// Return true if properties are changed; otherwise, returns false.
  /// </returns>
  virtual bool isModifiedForRecompute() const;

  virtual Acm::ErrorStatus getDisplayName(CString& rev) const;

  ///<summary>Override the function to erase associated AcDbDetailViewStyle.</summary>
  virtual Acad::ErrorStatus subErase (Adesk::Boolean isErasing); 

  ///<summary>This is record AmdtDetailSymStd::Variable.</summary>
  enum Variable {
    kLabelPattern = 0,
    kShowBorder,
    kShowConnectionLine,
    kShowAnnotLeader,
    kLabelAbove,
    kArrowHead
  };
  virtual Acm::Visibility variableStatus(AmdtDetailSymStd::Variable var) const;
  virtual void setVariableStatus(AmdtDetailSymStd::Variable var, Acm::Visibility status) const;
  ///<summary>Returns true if the text height associated to the by standard state for this symbol std is 
  ///a size up from the text height of the owning AcmStandard. Otherwise, returns false.</summary>
  virtual bool isHeightSizedUp() const;

  ///<summary>Set settings in AcDbDetailViewStyle to the same values as the corresponding settings in AmdtDetailSymStd.
  ///For example, it will call AcDbDetailViewStyle::setIdentifierPlacement() to set to AcDbDetailViewStyle::kOutsideBoundary.</summary>
  ///<param name="pDetailViewStyle">detail view style object.</param> 
  virtual void setDetailViewStyle(AcDbDetailViewStyle* pDetailViewStyle) const;

  /// <summary>
  /// Gets if the identifier is placed outside the boundary.
  /// </summary>
  ///
  /// <returns>
  /// Return Adesk::kTrue if the identifier is placed outside the boundary. 
  /// Return Adesk::kFalse if the identifier is placed on the boundary. 
  /// </returns>
  Adesk::Boolean  isIdentifierOutsideBoundary() const;

  /// <summary>
  /// Sets if the identifier is placed outside the boundary.
  /// </summary>
  ///
  /// <param name="outside">
  /// Adesk::kTrue to place identifier outside the boundary. 
  /// Adesk::kFalse to place the identifier on the boundary. 
  /// </param>
  void setIdentifierOutsideBoundary(Adesk::Boolean outside);

  /// <summary>
  /// Gets the color of the boundary line.
  /// </summary>
  ///
  /// <returns>
  /// Return color of the boundary line.
  /// </returns>
  AcCmColor boundaryLineColor() const;

  /// <summary>
  /// Sets the color of the boundary line.
  /// </summary>
  ///
  /// <param name="color">
  /// Color of the boundary line.
  /// </param>
  void setBoundaryLineColor(const AcCmColor & color);  

  /// <summary>
  /// Gets if the boundary line color follow the color of the Detail Border object in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if color follow the standard; otherwise, returns false.
  /// </returns>
  bool boundaryLineColorByStandard() const;

  /// <summary>
  /// Sets if the boundary line color follow the color of Detail Border object in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if color is to be set to the color of Detail Border object; false otherwise.
  /// </param>
  void setBoundaryLineColorByStandard(bool byStandard);

  /// <summary>
  /// Gets the linetype of the boundary line.
  /// </summary>
  ///
  /// <returns>
  /// Return object id of the linetype.
  /// </returns>
  AcDbObjectId boundaryLineId() const;

  /// <summary>
  /// Sets the linetype of the boundary line.
  /// </summary>
  ///
  /// <param name="idType">
  /// Object id of the linetype.
  /// </param>
  void setBoundaryLineId(const AcDbObjectId& idType);

  /// <summary>
  /// Gets if the linetype of the boundary line follow the linetype of the Detail Border object in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if linetype follow the standard; otherwise, returns false.
  /// </returns>
  bool boundaryLineIdByStandard() const;

  /// <summary>
  /// Sets if the linetype of the boundary line follow the linetype of Detail Border object in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if linetype is to be set to the linetype of Detail Border object; false otherwise.
  /// </param>
  void setBoundaryLineIdByStandard(bool byStandard);

  /// <summary>
  /// Gets the lineweight of the boundary line.
  /// </summary>
  ///
  /// <returns>
  /// Return lineweight of the boundary line.
  /// </returns>
  AcDb::LineWeight boundaryLineWeight() const;

  /// <summary>
  /// Sets the lineweight of the boundary line.
  /// </summary>
  ///
  /// <param name="lineWeight">
  /// Lineweight of the boundary line.
  /// </param>
  void setBoundaryLineWeight (AcDb::LineWeight lineweight);

  /// <summary>
  /// Gets if the lineweight of the boundary line follow the linetype of the Detail Border object in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if linetype follow the standard; otherwise, returns false.
  /// </returns>
  bool boundaryLineWeightByStandard() const;

  /// <summary>
  /// Sets if the lineweight of the boundary line follow the lineweight of Detail Border object in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if lineweight is to be set to the lineweight of Detail Border object; false otherwise.
  /// </param>
  void setBoundaryLineWeightByStandard(bool byStandard);

  /// <summary>
  /// Gets the color of the border line.
  /// </summary>
  ///
  /// <returns>
  /// Return color of the border line.
  /// </returns>
  AcCmColor borderLineColor () const;

  /// <summary>
  /// Sets the color of the border line.
  /// </summary>
  ///
  /// <param name="color">
  /// Color of the border line.
  /// </param>
  void setBorderLineColor (const AcCmColor& color);

  /// <summary>
  /// Gets if the border line color follow the color of the Detail Border object in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if color follow the standard; otherwise, returns false.
  /// </returns>
  bool borderLineColorByStandard() const;

  /// <summary>
  /// Sets if the linetype of the border line follow the linetype of Detail Border object in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if linetype is to be set to the linetype of Detail Border object; false otherwise.
  /// </param>
  void setBorderLineColorByStandard(bool byStandard);

  /// <summary>
  /// Gets the linetype of the border line.
  /// </summary>
  ///
  /// <returns>
  /// Return object id of the linetype.
  /// </returns>
  AcDbObjectId borderLineId () const;

  /// <summary>
  /// Sets the linetype of the border line.
  /// </summary>
  ///
  /// <param name="lineId">
  /// Object id of the linetype.
  /// </param>
  void setBorderLineId (const AcDbObjectId &lineId);

  /// <summary>
  /// Gets if the linetype of the border line follow the linetype of the Detail Border object in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if linetype follow the standard; otherwise, returns false.
  /// </returns>
  bool borderLineIdByStandard() const;

  /// <summary>
  /// Sets if the linetype of the border line follow the linetype of Detail Border object in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if linetype is to be set to the linetype of Detail Border object; false otherwise.
  /// </param>
  void setBorderLineIdByStandard(bool byStandard);

  /// <summary>
  /// Gets the lineweight of the border line.
  /// </summary>
  ///
  /// <returns>
  /// Return lineweight of the border line.
  /// </returns>
  AcDb::LineWeight  borderLineWeight () const;

  /// <summary>
  /// Sets the lineweight of the border line.
  /// </summary>
  ///
  /// <param name="lineWeight">
  /// Lineweight of the border line.
  /// </param>
  void setBorderLineWeight (AcDb::LineWeight lineweight);

  /// <summary>
  /// Gets if the lineweight of the border line follow the linetype of the Detail Border object in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if linetype follow the standard; otherwise, returns false.
  /// </returns>
  bool borderLineWeightByStandard() const;

  /// <summary>
  /// Sets if the lineweight of the border line follow the lineweight of Detail Border object in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if lineweight is to be set to the lineweight of Detail Border object; false otherwise.
  /// </param>
  void setBorderLineWeightByStandard(bool byStandard);

  /// <summary>
  /// Gets the color of the connection line.
  /// </summary>
  ///
  /// <returns>
  /// Return color of the connection line.
  /// </returns>
  AcCmColor connectionLineColor () const;

  /// <summary>
  /// Sets the color of the connection line.
  /// </summary>
  ///
  /// <param name="color">
  /// Color of the connection line.
  /// </param>
  void setConnectionLineColor (const AcCmColor& color);

  /// <summary>
  /// Gets if the connection line color follow the color of the Detail Border object in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if color follow the standard; otherwise, returns false.
  /// </returns>
  bool connectionLineColorByStandard() const;

  /// <summary>
  /// Sets if the linetype of the connection line follow the linetype of Detail Border object in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if linetype is to be set to the linetype of Detail Border object; false otherwise.
  /// </param>
  void setConnectionLineColorByStandard(bool byStandard);

  /// <summary>
  /// Gets the linetype of the connection line.
  /// </summary>
  ///
  /// <returns>
  /// Return object id of the linetype.
  /// </returns>
  AcDbObjectId connectionLineId () const;

  /// <summary>
  /// Sets the linetype of the connection line.
  /// </summary>
  ///
  /// <param name="lineId">
  /// Object id of the linetype.
  /// </param>
  void setConnectionLineId (const AcDbObjectId &lineId);

  /// <summary>
  /// Gets if the linetype of the connection line follow the linetype of the Detail Border object in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if linetype follow the standard; otherwise, returns false.
  /// </returns>
  bool connectionLineIdByStandard() const;

  /// <summary>
  /// Sets if the linetype of the connection line follow the linetype of Detail Border object in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if linetype is to be set to the linetype of Detail Border object; false otherwise.
  /// </param>
  void setConnectionLineIdByStandard(bool byStandard);

  /// <summary>
  /// Gets the lineweight of the connection line.
  /// </summary>
  ///
  /// <returns>
  /// Return lineweight of the connection line.
  /// </returns>
  AcDb::LineWeight connectionLineWeight () const;

  /// <summary>
  /// Sets the lineweight of the connection line.
  /// </summary>
  ///
  /// <param name="lineWeight">
  /// Lineweight of the connection line.
  /// </param>
  void setConnectionLineWeight (AcDb::LineWeight lineweight);

  /// <summary>
  /// Gets if the lineweight of the connection line follow the linetype of the Detail Border object in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if linetype follow the standard; otherwise, returns false.
  /// </returns>
  bool connectionLineWeightByStandard() const;

  /// <summary>
  /// Sets if the lineweight of the connection line follow the lineweight of Detail Border object in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if lineweight is to be set to the lineweight of Detail Border object; false otherwise.
  /// </param>
  void setConnectionLineWeightByStandard(bool byStandard);

  /// <summary>
  /// Gets if show label.
  /// </summary>
  ///
  /// <returns>
  /// Return true if label is shown; otherwise, returns false.
  /// </returns>
  bool showLabel () const;

  /// <summary>
  /// Sets if show label.
  /// </summary>
  ///
  /// <param name="showLabel">
  /// true to show label; false otherwise.
  /// </param>
  void setShowLabel (bool showLabel);

  /// <summary>
  /// Gets the text style of the label.
  /// </summary>
  ///
  /// <returns>
  /// Return object id of the text style.
  /// </returns>
  AcDbObjectId labelTextStyleId () const;

  /// <summary>
  /// Sets the text style of the label.
  /// </summary>
  ///
  /// <param name="textStyleId">
  /// Object id of the text style.
  /// </param>
  void setLabelTextStyleId (const AcDbObjectId &textStyleId);

  /// <summary>
  /// Gets if the text style of the label follow the text style of the text in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if text style follow the standard; otherwise, returns false.
  /// </returns>
  bool labelTextStyleByStandard() const;

  /// <summary>
  /// Sets if the text style of the label follow the text style of the text in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if text style of the label is to be set to the text style of the text in standard; false otherwise.
  /// </param>
  void setLabelTextStyleByStandard(bool byStandard);

  /// <summary>
  /// Gets the text color of the label.
  /// </summary>
  ///
  /// <returns>
  /// Return text color of the label.
  /// </returns>
  AcCmColor labelTextColor () const;

  /// <summary>
  /// Sets the text color of the label.
  /// </summary>
  ///
  /// <param name="color">
  /// Text color of the label.
  /// </param>
  void setLabelTextColor (const AcCmColor& color);

  /// <summary>
  /// Gets if the text color of the label follow the color of the text in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if text color follow the standard; otherwise, returns false.
  /// </returns>
  bool labelTextColorByStandard() const;

  /// <summary>
  /// Sets if the text color of the label follow the color of the text in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if text color of the label is to be set to the color of the text in standard; false otherwise.
  /// </param>
  void setLabelTextColorByStandard(bool byStandard);

  /// <summary>
  /// Gets the text height of the label.
  /// </summary>
  ///
  /// <returns>
  /// Return text height of the label.
  /// </returns>
  double labelTextHeight () const;

  /// <summary>
  /// Sets the text height of the label.
  /// </summary>
  ///
  /// <param name="height">
  /// Text height of the label.
  /// </param>
  /// <returns>
  /// Return Acad::eOk if Successful.
  /// </returns>
  Acad::ErrorStatus setLabelTextHeight (double height);

  /// <summary>
  /// Gets if the text height of the label follow the height of the text in standard.
  /// </summary>
  ///
  /// <returns>
  /// Return true if text height follow the standard; otherwise, returns false.
  /// </returns>
  bool labelTextHeightByStandard() const;

  /// <summary>
  /// Sets if the text height of the label follow the height of the text in standard.
  /// </summary>
  ///
  /// <param name="byStandard">
  /// true if text height of the label is to be set to the height of the text in standard; false otherwise.
  /// </param>
  void setLabelTextHeightByStandard(bool byStandard);

  /// <summary>
  /// Gets the label offset from the view.
  /// </summary>
  ///
  /// <returns>
  /// Return label offset from the view.
  /// </returns>
  double labelOffset () const;

  /// <summary>
  /// Sets the label offset from the view.
  /// </summary>
  ///
  /// <param name="offset">
  /// Label offset from the view.
  /// </param>
  /// <returns>
  /// Return Acad::eOk if Successful.
  /// </returns
  Acad::ErrorStatus setLabelOffset (double offset);

protected:
  AmdtDetailSymStd();
  virtual Acad::ErrorStatus createDefaultLTypeAnnotLine(LPCTSTR pName);
  Acad::ErrorStatus preMigratePreKastle();
  Acad::ErrorStatus migratePreKastle(AmdtDetailSymStdLegacyImp *pLegacyDetailStd);
   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;
  // PKA 01/22/2013: Bugfix DID 1490557
  virtual Acad::ErrorStatus subDeepClone(AcDbObject*    pOwnerObject,
                                      AcDbObject*&   pClonedObject,
                                      AcDbIdMapping& idMap,
                                      Adesk::Boolean isPrimary = Adesk::kTrue) const;
  AcDbObjectId detailViewStyleId () const;
  Acad::ErrorStatus setDetailViewStyleId (const AcDbObjectId &viewStyleId);


  const AmdtDetailSymStdImp * constImp() const;
  AmdtDetailSymStdImp *       imp();

  virtual void setFactoryDefaultsOnNewSettings(); // new settings in Kastle

  void getSubEntsSourceGeomOutsideBoundary(const AmdtDetailSymC* pSymb,AcmCAuxEntArray& subents, const AcCmColor& symColor) const;
  void getSubEntsSourceGeomOnBoundary(const AmdtDetailSymC* pSymb,AcmCAuxEntArray& subents, const AcCmColor& symColor, AcDbDatabase *pDb) const;

  bool drawIdentifierOutsideBoundary(const AcDbCurve* pSourceGeom) const;

};

inline
const AmdtDetailSymStdImp* AmdtDetailSymStd ::constImp() const
{
    ASSERT(mpSymStdImp);
    return (const AmdtDetailSymStdImp*)mpSymStdImp;
}

inline
AmdtDetailSymStdImp* AmdtDetailSymStd ::imp()
{
    ASSERT(mpSymStdImp);
    return (AmdtDetailSymStdImp*)mpSymStdImp;
}

DBREF_DECLARE(AmdtDetailSymStd)

///<summary>Detail symbol object class.</summary>
class ACMSYMBB_CRX_DLLSHARE AmdtDetailSym : public AcmSymbol
{
public:
  ACRX_DECLARE_MEMBERS(AmdtDetailSym);
  ///<param name="detailScale ">baseViewId :</param>
  AmdtDetailSym(const AcGePoint3d& origin = AcGePoint3d::kOrigin,
                const double detailScale = 1.0,
                const AcDbObjectId& baseViewId = NULL);
  virtual ~AmdtDetailSym();             
  AcDbObjectId detailViewId() const;
  AcDbObjectId baseViewId() const;
  ///<summary>Returns the origin of the defining plane.</summary>
  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);

  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();

  Acm::ErrorStatus getLabelNames(AcStringArray& label) const override;
  const ACHAR* labelName() const;

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

  CString labelText() const;
  bool isShowBorder() const;
  void setShowBorder( bool bVal);
  bool isShowLeader() const;
  void setShowLeader( bool bVal);

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

  ///<summary>this one is for AmdtDetailSym, we have to be able to change the geometry (in transformBy)</summary>
  AcDbCurve* sourceGeom() const;
  LPCTSTR value(Acm::Variable var) const;
  Acm::ErrorStatus setValue(Acm::Variable var, LPCTSTR value);
  
  Acm::Visibility  variableStatus(Acm::Variable var) const;
  ///<param name="val">status :</param>
  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;
  ///<summary>Transforms all leaders. Default implementation doesn't cover any smart behavior.</summary>
  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);


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

  ///<summary>It prepares mSourceGeom from an existing geometry</summary>
  Acad::ErrorStatus makeSourceGeom(AcDbCurve* pSourceGeom);
  ///<summary>It creates circle source geom</summary>
  Acad::ErrorStatus makeSourceGeom(const AcGePoint3d& center, 
                                   const AcGeVector3d& normal, 
                                   const double radius);
  ///<summary>It creates ellipse source geom</summary>
  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);

  ///<summary>Queries all leaders for their grip points.</summary>
  virtual Acad::ErrorStatus subGetGripPoints(AcGePoint3dArray&,
                                          AcDbIntArray&,
                                          AcDbIntArray&) const;

  ///<summary>Queries all leaders for their grip points.</summary>
  virtual Acad::ErrorStatus   subGetGripPoints(AcDbGripDataPtrArray& grips,
														  const double curViewUnitSize, 
														  const int gripSize, 
													     const AcGeVector3d& curViewDir, 
														  const int bitflags) const;

  ///<summary>Determines the leaders to which indices belong and apply moveGripPointsAt to them. If the 
  ///tip point is being edited, then the leaderTipPointChanged() member function of the symbol will be
  ///called. If the leader contains a landing and it is changed, then the leaderLanding() member function
  ///of the symbol is called.</summary>
  virtual Acad::ErrorStatus subMoveGripPointsAt(const AcDbIntArray& indices,
                                             const AcGeVector3d& offset); 

  ///<summary>Queries the standard for sub-entities for all leaders and then the server for all sub-entities
  ///for all sub-symbols. All sub-entities are then exploded.</summary>
  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;
  ///<summary>Sums geometry extents for a leader.</summary>
  virtual Acad::ErrorStatus subGetGeomExtents(AcDbExtents& extents) const;

  void updateAnnotOffsets (const double scale);
  void updateDetail2d (const AcGeMatrix3d& xform);

  AmdtDetailSymC* mpSubSymbol;
};    
DBREF_DECLARE(AmdtDetailSym);

///<summary>The detail symbol label class.</summary>
class ACMSYMBB_CRX_DLLSHARE AmdtDetailSymLabel : public AcmSymbol
{
  friend class AcmSymbbInternals;
public:
  ACRX_DECLARE_MEMBERS(AmdtDetailSymLabel);
  ///<param name="origin">detailViewId :</param>
  AmdtDetailSymLabel(const AcGePoint3d& origin = AcGePoint3d::kOrigin,
                   const AcDbObjectId& detailViewId = NULL);
  virtual ~AmdtDetailSymLabel();

  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;

  ///<summary>Returns the origin of the defining plane.</summary>
  virtual AcGePoint3d origin() const;
  ///<summary>Sets the origin of the defining plane.</summary>
  virtual void setOrigin(const AcGePoint3d& origin);
  AcGeVector3d annotOffset() const;

  void setAnnotOffset(const AcGeVector3d& vect);
  void updateAnnotOffset(const double scale);
  AcDbObjectId symbolEntId () const;
  void setSymbolEntId (const AcDbObjectId& id);
  void highlightAll();
  void unhighlightAll();

  using AcmSymbol::transformBy;
  ///<summary>Transforms all leaders. Default implementation doesn't cover any smart behavior.</summary>
  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);
  ///<summary>This function is called during the updating of symbols that takes place when the standard is changed.</summary>
  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;

  ///<summary>Queries all leaders to get their interDetails with the specified entity. If it is a 
  ///user-defined entity, it will be exploded first, and created entities will be resolved using the
  ///same member function.</summary>
  virtual Acad::ErrorStatus subIntersectWith(const AcDbEntity* pEnt,AcDb::Intersect intType,
                            AcGePoint3dArray& points,INT_PTR thisGsMarker = 0,INT_PTR otherGsMarker= 0) const;

  ///<summary>Sums geometry extents for a leader.</summary>
  virtual Acad::ErrorStatus subGetGeomExtents(AcDbExtents& extents) const;
  ///<summary>Queries all leaders for their grip points.</summary>
  virtual Acad::ErrorStatus subGetGripPoints(AcGePoint3dArray&,
                                          AcDbIntArray&,
                                          AcDbIntArray&) const;
  ///<summary>Queries all leaders for their grip points.</summary>
  virtual Acad::ErrorStatus	subGetGripPoints(AcDbGripDataPtrArray& grips,
                                            const double curViewUnitSize, 
                                            const int gripSize, 
                                            const AcGeVector3d& curViewDir, 
                                            const int bitflags) const;

  ///<summary>Determines the leaders to which indices belong and apply moveGripPointsAt to them. If the tip
  ///point is being edited, then the leaderTipPointChanged() member function of the symbol will be called.
  ///If the leader contains a landing and it is changed, then the leaderLanding() member function of the symbol is called.</summary>
  virtual Acad::ErrorStatus subMoveGripPointsAt(const AcDbIntArray& indices,
                                             const AcGeVector3d& offset); 

  ///<summary>Queries the standard for sub-entities for all leaders and then the server for all sub-entities
  ///for all sub-symbols. All sub-entities are then exploded.</summary>
  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;
};
DBREF_DECLARE(AmdtDetailSymLabel)

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

///<summary>This is class AmdtDetailSymEnt.</summary>
class ACMSYMBB_CRX_DLLSHARE 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); }
};    

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

///<summary>This is class AmdtDetailSymC.</summary>
class AmdtDetailSymC : public AcmCSubSymbol
{
    friend class AmdtDetailSymCImp;
public:

  AmdtDetailSymC(AmdtDetailSym* pSym, const AcGePoint3d& origin = AcGePoint3d::kOrigin, const double detailScale = 1.0, const AcDbObjectId& baseViewId = NULL);
  virtual ~AmdtDetailSymC();

  // Copy constructor
  AmdtDetailSymC(const AmdtDetailSymC& other);

  Adesk::Boolean operator==(const AmdtDetailSymC&) const;
  virtual AmdtDetailSymC& operator=(const AmdtDetailSymC&);
  virtual AmdtDetailSymC* clone()const;
  virtual void clear();

  AmdtDetailSymCImp* getImp() const { return mpImp; }

  virtual const AcDbCurve* sourceGeometry() const;
  virtual AcGeVector3d annotOffset() const;
  virtual void setAnnotOffset(const AcGeVector3d& offset);
  virtual AcGeVector3d labelEntOffset() const;
  virtual void setLabelEntOffset(const AcGeVector3d& offset);
  virtual double radius() const;
  virtual void setRadius(const double radius);
  virtual double detailScale() const;
  virtual void setDetailScale(const double scale);
  virtual double correctionScaleFactor() const;
  virtual void setCorrectionScaleFactor(const double scale);
  virtual double baseViewScale() const;
  virtual void setBaseViewScale(const double scale);
  virtual const ACHAR* labelName() const;
  virtual void setLabelName(const ACHAR* labelName);
  virtual const ACHAR* labelPattern() const;
  virtual void setLabelPattern(const ACHAR* labelPattern);
  virtual CString labelText() const;
  virtual Adesk::Boolean isShowBorder() const;
  virtual void setShowBorder(const Adesk::Boolean v);
  virtual Adesk::Boolean isShowLeader() const;
  virtual void setShowLeader(const Adesk::Boolean v);
  virtual Adesk::Boolean isShowAnnotLeader() const;
  virtual void setShowAnnotLeader(const Adesk::Boolean v);
  virtual AcGePoint3dArray leaderPoints() const;
  virtual void setLeaderPoints(const AcGePoint3dArray& leaderPoints);
  virtual void addLeaderPoint(const AcGePoint3d& point);
  virtual void eraseLeaderPoints();

  virtual double scale() const;
  virtual AcGeVector3d normal() const;
  virtual AcGeVector3d xDir() const;
  virtual AcGeVector3d yDir() const;
  virtual AcDbObjectId labelEntId() const;
  virtual int  detailSpace () const;
  virtual void setDetailSpace (int space);

  virtual AcGePoint3d origin() const override;
  ///<summary>Sets the origin of the symbol in WCS.</summary>
  virtual void setOrigin(const AcGePoint3d& origin) override;
  ///<summary>Gets the value of any symbol variable.</summary>
  virtual LPCTSTR value(Acm::Variable var) const override;
  ///<summary>Gets the value of any symbol variable.</summary>
  virtual Acm::ErrorStatus getValue(Acm::Variable var, CString& value) const override;
  ///<summary>Sets the value of any symbol variable.</summary>
  virtual Acm::ErrorStatus setValue(Acm::Variable var, LPCTSTR value) override;
  ///<summary>Gets the visibility status of the editing controls.</summary>
  virtual Acm::Visibility  variableStatus(Acm::Variable var) const override;
  ///<summary>Sets the visibility status of the editing controls.</summary>
  virtual Acm::ErrorStatus setVariableStatus(Acm::Variable var, Acm::Visibility status) override;
  ///<summary>Gets the variable support data, such as the help index, dialog index, tooltip string, and label string.</summary>
  virtual Acm::ErrorStatus getVarDlgInfo(Acm::Variable var, CVarDlgInfo& v) const override;
  ///<summary>Sets the variable support data, such as the help index, dialog index, tooltip string, and label string.</summary>
  virtual Acm::ErrorStatus setVarDlgInfo(Acm::Variable var, const CVarDlgInfo& v) override;


  virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer, Adesk::UInt16 ver) override;
  virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const override;

  Acad::ErrorStatus varInFields(const AcmVariant* pVar, AcRxObject* pFiler = nullptr) override;
  Acad::ErrorStatus varOutFields(AcmVariant* pVar, AcRxObject* pFiler = nullptr) const override;


  virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* filer) override;
  virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* filer) const override;

private: 
    AmdtDetailSymCImp* mpImp{ nullptr };
};

#endif // __DETAILSYM_H
