//////////////////////////////////////////////////////////////////////////////
//
//  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 __DATUMTGT_H
#define __DATUMTGT_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

#include "AdAChar.h"

class AcmCTarget;
class AcmCTargetBalloon;
class AcmCTargetService;
class AcmCDatumTargetImp;
class AcmDatumStdImp;
class AcmCTargetImp;

///<summary>This class is responsible for datum target sub-symbols. It contains several services that 
///allow it to handle all types of target symbols.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmDatumStd : public AcmSymbolStd
{
  friend class AcmSymbbInternals;
public:
  ACRX_DECLARE_MEMBERS(AcmDatumStd);
  ///<summary>Destructures the datum target standard class.</summary>
  virtual ~AcmDatumStd();
  ///<summary>This class implementation doesn't do anything and returns eNotImplemented if it is not
  ///overloaded in the child class.</summary>
  virtual Acm::ErrorStatus cInit();
  virtual Acm::ErrorStatus getDescription(CString& desc,
                                          CBitmap*& pBmpLoaded,
                                          CBitmap*& pBmpReg,
                                          Adesk::Boolean& enablePref) const;
  void initToEditOriginal()const override;
  void initToEdit()const override;
  const ACHAR* getBaseSymStdClassName() const override;
  ///<summary>Gets the special datum target leader, which expresses to be connected to the hidden target
  ///(the target point is attached to the hidden geometry).</summary>
  AcDbObjectId hiddenLeaderLineId() const;
  ///<summary>Creates a special datum target leader, which expresses to be connected to the hidden target 
  ///(the target point is attached to the hidden geometry).</summary>
  Acm::ErrorStatus setHiddenLeaderLineId(const AcDbObjectId& idType);
  
  Acm::ErrorStatus getHiddenLeaderLtypeName(ACHAR*& pName) const;
  ///<summary>Creates a special datum target leader, which expresses to be connected to the hidden target 
  ///(the target point is attached to the hidden geometry).</summary>
  Acm::ErrorStatus setHiddenLeaderLtypeName(const ACHAR* pName);
  ///<summary>Gets the line type used to draw the borderline of a target symbol.</summary>
  AcDbObjectId borderLineId() const;
  ///<summary>Sets the line type used to draw the borderline of a target symbol.</summary>
  Acm::ErrorStatus setBorderLineId(const AcDbObjectId& idType);
  Acm::ErrorStatus getBorderLtypeName(ACHAR*& pName) const;
  Acm::ErrorStatus setBorderLtypeName(const ACHAR* pName);
  ///<summary>Gets whether to use the leader arrowhead for all leaders. If not, then kNoArrow is used as 
  ///the arrowhead type for this leader.</summary>
  Adesk::Boolean drawLeaderArrow() const;
  ///<summary>Sets whether to use the leader arrowhead for all leaders. If not, then kNoArrow is used as 
  ///the arrowhead type for this leader.</summary>
  void setDrawLeaderArrow(Adesk::Boolean status);
  ///<summary>Gets the hatch angle for hatching inside the rectangular or circular area.</summary>
  double hatchAngle() const;
  ///<summary>Sets the hatch angle for hatching inside the rectangular or circular area.</summary>
  void setHatchAngle(double value);
  ///<summary>Gets the distance between hatch lines.</summary>
  double hatchDist() const;
  ///<summary>Sets the distance between hatch lines.</summary>
  void setHatchDist(double value);
  ///<summary>Gets the special color override for points used in point target and linear target symbols.</summary>
  Adesk::UInt16 pointColor() const;
  ///<summary>Sets the special color override for points used in point target and linear target symbols.</summary>
  void setPointColor(Adesk::UInt16 color);
  const AcCmColor & pointTrueColor() const;
  void setPointTrueColor(const AcCmColor & color);
  ///<summary>Gets the size of the point symbol used in point target and linear target symbols.</summary>
  double pointSize() const;
  ///<summary>Sets the size of the point symbol used in point target and linear target symbols.</summary>
  void setPointSize(double value);
  ///<summary>For internal use only.
  ///Gets the line type used to draw Line temination type</summary>
  AcDbObjectId lineTermLineId() const;
  ///<summary>For internal use only.</summary>
  Adesk::Boolean  useBorderLtypeforLineTerm() const;
  ///<summary>For internal use only.
  /// Sets whether we use Border linetype for Line temination type. If true,
  /// lineTermLineId() will return same as borderLineId(). If sets it false, lineTermLineId()
  /// will return standard leader line type </summary>
  void  setUseBorderLtypeforLineTerm(Adesk::Boolean status);
  ///<summary>Sets the factory default values.</summary>
  virtual Adesk::Boolean setFactoryDefaults();
  
  virtual Acm::ErrorStatus checkVisibility(AcmCTargetBalloon* pData) const;
  virtual Acm::ErrorStatus initFields(AcmCTargetBalloon* pData) const;
  virtual Acm::ErrorStatus setSuggested(AcmCTargetBalloon* pData) const;
  ///<summary>Gets the sub entities of the datum standard.</summary>
  ///<param name="trans">Specifies the transformation matrix for the sub-symbol. The sub-symbol should not
  ///be transformed.</param>
  virtual void getSubEnts(const AcmCSubSymbol* pSymb,
                          AcmCAuxEntArray& subents,
                          const AcGeMatrix3d& trans) const;

  virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
  virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;
  virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* filer);
  virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* filer) const;
  ///<summary>Gets the specified service to use for getting sub-entities.</summary>
  AcmCTargetService* getService(Acm::TargetType type) const;

  virtual Acad::ErrorStatus getAllowedBallonAngle(double& angle, bool& isLeaderAng, const AcmSymbol* pSymbol) const;

protected:
  ///<summary>Constructs the datum target standard class. The constructor is protected.</summary>
  AcmDatumStd();
  ///<summary>Registers the target service for use.</summary>
  Adesk::Boolean registerService(AcmCTargetService* pNewServ);
  virtual Acm::ErrorStatus createDefaultLTypeBorderLine(const ACHAR* name);
  virtual Acm::ErrorStatus createDefaultLTypeHiddenLeaderLine(const ACHAR* name);
  virtual Acad::ErrorStatus  subGetClassID(CLSID* pClsid) const;

private:
  AcmDatumStdImp* mpImp;
};
DBREF_DECLARE(AcmDatumStd)

///<summary>This class has more complex grip points editing, because it contains more independent sub
///symbols - one balloon and one target sub-symbol. They are closely related to their leaders.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmDatumTarget : public AcmSymbol
{
public:
  ACRX_DECLARE_MEMBERS(AcmDatumTarget);
  ///<summary>This constructor creates the symbol using a specific target type.</summary>
  AcmDatumTarget();
  ///<summary>This constructor creates the symbol using a specific target type.</summary>
  AcmDatumTarget(Acm::TargetType type);
  ///<summary>Destructures the datum target class.</summary>
  virtual ~AcmDatumTarget();
  
  LPCTSTR value(Acm::Variable var) const;
  Acm::ErrorStatus setValue(Acm::Variable var, LPCTSTR value);
  ///<summary>Gets the visibility status of the editing controls. It can be kHidden, kDisabled, kShaded,
  ///kSelectOnly, kVisible, where kDisabled, kShaded and kSelectOnly have the same meaning.</summary>
  Acm::Visibility  variableStatus(Acm::Variable var) const;
  ///<summary>Sets the visibility status of the editing controls.</summary>
  ///<param name="status">It can be kHidden, kDisabled, kShaded, kSelectOnly, kVisible, where kDisabled, 
  ///kShaded and kSelectOnly have the same meaning.</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);

  Acm::Orientation orientation() const;
  void setOrientation(Acm::Orientation o);

  Adesk::Boolean isMovable() const;
  void setMovable(Adesk::Boolean value);
  
  virtual AcmCTarget *getNewTarget(Acm::TargetType type);
  ///<summary>Uses this overloaded member function to set up a symbol properly.</summary>
  virtual Acm::ErrorStatus setSymbolDefaults(AcDbDatabase* pDb = NULL);
  AcmCTargetBalloon* balloon() const;
  AcmCTarget* target() const;
  ///<summary>This function is called during the updating of symbols that takes place when the standard is changed.</summary>
  virtual void regen();
  double balloonRadius() const;
  void setLTypeIdToHidden();
  void setLTypeIdToSolid();
  Adesk::Boolean isHidden() const;

  void setHidden(Adesk::Boolean val);
  ///<summary>Sends a notification if the tip point of the leader has changed.</summary>
  virtual void leaderTipPointChanged(const AcGeVector3d& offset,
                                     const AcmCLeader* leader);
  
  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);
  ///<summary>This method mirrors AcmSymbol entity.</summary>
  ///<param name:"xMirrorForm">Transformation matrix with MIRROR element</param>
  ///<param name:"XAxis">Returns mirrored X-Axis of the entity coordinate system</param>
  ///<param name:"YAxis">Returns mirrored Y-Axis of the entity coordinate system</param>
  ///<param name:"normal">Returns mirrored Normal of the entity coordinate system</param>
  virtual void mirrorCoordSys(const AcGeMatrix3d& xMirrorForm,
                              AcGeVector3d& XAxis,
                              AcGeVector3d& YAxis,
                              AcGeVector3d& normal) const;

  virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
  virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;
  virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* filer);
  virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* filer) const;
  virtual void updateLeader();
  
  virtual Acm::ErrorStatus attachGeomRef(const void* pGeomRef,
                                         const AcDbObjectId &viewId,
                                         const AcGePoint3d &arrowheadLocation);

  virtual Acm::ErrorStatus attachGeomRef(const void* pGeomRef,
                                         const AcGePoint3d &arrowheadLocation);

  bool setTargetAttach(const AcmDatumTarget* pDatumTarget, const Acm::AttachPosition position);
  virtual Acm::ErrorStatus addLeader(const AcGePoint3dArray& ptrArray);

protected:
  virtual Adesk::Boolean    subWorldDraw(AcGiWorldDraw* pMode);
  ///<summary>Gets the symbol class ID.</summary>
  virtual Acad::ErrorStatus   subGetClassID(CLSID* pClsid) const;
  ///<summary>Sums geometry extents for a leader.</summary
  virtual Acad::ErrorStatus subGetOsnapPoints (AcDb::OsnapMode, INT_PTR,
                                               const AcGePoint3d&,
                                               const AcGePoint3d&,
                                               const AcGeMatrix3d&,
                                               AcGePoint3dArray&,
                                               AcDbIntArray&) 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>Implemented by calling the getGripPoints member function.</summary>
  virtual Acad::ErrorStatus subGetStretchPoints(AcGePoint3dArray&) 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 subMoveStretchPointsAt(const AcDbIntArray& indices,
                                                   const AcGeVector3d& offset);
  virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d& xform);
  ///<summary>Sums geometry extents for a leader.</summary>
  virtual Acad::ErrorStatus subGetGeomExtents(AcDbExtents&) const;
  ///<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 void              subList() const;

private:
  void updateOrigin();
  void updateBallon();
  void GetBallonGripPoints(AcGePoint3dArray& gripPoints) const;
  void GetDimensionNoteGripPoints(AcGePoint3dArray& gripPoints) const;
  bool calcLeaderNoteGripShifting(const AcGeVector3d& offset);
  bool calcBallonGripRotattion(const AcGeVector3d& proOff,
                               int idxBall);

  AcmCDatumTargetImp* mpImp;
};                      
DBREF_DECLARE(AcmDatumTarget)

///<summary>This symbol defines a common interface for all target types. Extended interfaces are implemented.</summary>
class AcmCTarget : public AcmCSubSymbol
{
protected:
  AcmCTarget(AcmCTargetImp* pImp);

public:
  virtual ~AcmCTarget();

  AcmCTargetImp* getImp() const { return mpImp; }

  Adesk::Boolean operator==(const AcmCTarget&) const;
  virtual AcmCTarget& operator=(const AcmCTarget&);

  virtual Acm::TargetType type() const;
  virtual double scale() const;

  virtual void getDefaultText(CString& text) const;

  virtual AcGePoint3d recalcLeaderStart(const AcGePoint3d& pnt) const;
  
  virtual Acad::ErrorStatus getGripPoints(AcGePoint3dArray&  gripPoints,
                                          AcDbIntArray&  osnapModes,
                                          AcDbIntArray&  geomIds) const;
  
  virtual Acad::ErrorStatus moveGripPointsAt(const AcDbIntArray& indices,
                                             const AcGeVector3d& offset);
  ///<summary>Implemented by calling the moveGripPointsAt member function.</summary>
  virtual Acad::ErrorStatus moveStretchPointsAt(const AcDbIntArray& indices,
                                                const AcGeVector3d& offset);
  ///<summary>Returns the number of grip points used by this class.</summary>
  virtual int numGripPoints() const;

  virtual Adesk::Boolean isKnownGrip(int indice) const;
  virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform);

  virtual AcGePoint3d origin() const;
  ///<summary>Sets the origin of the symbol in WCS.</summary>
  virtual void setOrigin(const AcGePoint3d& origin);
  ///<summary>Gets the value of any symbol variable.</summary>
  virtual LPCTSTR value(Acm::Variable var) const;
  ///<summary>Gets the value of any symbol variable.</summary>
  virtual Acm::ErrorStatus getValue(Acm::Variable var, CString& value) const;
  ///<summary>Sets the value of any symbol variable.</summary>
  virtual Acm::ErrorStatus setValue(Acm::Variable var, LPCTSTR value);
  ///<summary>Gets the visibility status of the editing controls.</summary>
  virtual Acm::Visibility  variableStatus(Acm::Variable var) const;
  ///<summary>Sets the visibility status of the editing controls.</summary>
  virtual Acm::ErrorStatus setVariableStatus(Acm::Variable var, Acm::Visibility status);
  ///<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;
  ///<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);


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

  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);
  virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* filer) const;

protected:
    AcmCTargetImp* mpImp{ nullptr };
};   
///<summary>It is inherited from AcmCTarget. The basic interface is implemented as described in
///AcmCSubSymbol and AcmCTarget.</summary>
class AcmCTargetBalloon : public AcmCTarget
{
public:
  AcmCTargetBalloon(AcmDatumTarget* pSym);

  virtual Acm::Orientation orientation() const;
  virtual void setOrientation(Acm::Orientation o);

  virtual Adesk::Boolean isMovable(bool bCheck = true) const;
  virtual void setMovable(Adesk::Boolean value);
  virtual bool movableAllowed() const;

  virtual Acm::TargetType symbolType() const;

  virtual double angle() const;
  virtual bool isAngleOfLeaderSegment() const;
  virtual const AcGeVector3d& outsideTextShifting() const;
  virtual bool textIsOutside()const;
};

///<summary>It is inherited from AcmCTarget. The basic interface is implemented as described in 
///AcmCSubSymbol and AcmCTarget.</summary>
class AcmCTargetPoint : public AcmCTarget
{
public:
  AcmCTargetPoint(AcmDatumTarget* pSymbol, Adesk::Boolean drawPoint = Adesk::kTrue, bool isAttached = false);

  virtual Adesk::Boolean drawPoint() const;
  virtual void setDrawPoint(Adesk::Boolean flag);
};
///<summary>It is inherited from AcmCTarget. The basic interface is implemented as described in 
///AcmCSubSymbol and AcmCTarget.</summary>
class AcmCTargetLine : public AcmCTarget
{
public:
  AcmCTargetLine(AcmDatumTarget* pSym);

  virtual Adesk::Boolean drawLine() const;
  virtual void setDrawLine(Adesk::Boolean flag);
  virtual AcGePoint3d endPoint() const;
  virtual void setEndPoint(const AcGePoint3d& point);
  virtual double factor() const;
  virtual void setFactor(double f);
  virtual AcGePoint3d midPoint() const;
};

///<summary>It is inherited from AcmCTarget. The basic interface is implemented as described in 
///AcmCSubSymbol and AcmCTarget.</summary>
class AcmCTargetCircularArea : public AcmCTarget
{
public:
  AcmCTargetCircularArea(AcmDatumTarget* pSym);

  virtual double radius() const;
  virtual void setRadius(double r);
};
///<summary>It is inherited from AcmCTarget. The basic interface is implemented as described in
///AcmCSubSymbol and AcmCTarget.</summary>
class AcmCTargetRectangularArea : public AcmCTarget
{
public:
  AcmCTargetRectangularArea(AcmDatumTarget* pSym);

  virtual double angle() const;
  virtual void setAngle(double aplha);
  virtual double xSize() const;
  virtual void setXSize(double x);
  virtual double ySize() const;
  virtual void setYSize(double y);
  virtual AcGePoint3d cornerPoint() const;
  virtual void setCornerPoint(const AcGePoint3d& pt);
  virtual AcGePoint3d anglePoint() const;
  virtual void setAnglePoint(const AcGePoint3d& pt);
};                      
///<summary>These services do not contain data and they are not filled out to drawing. 
///There are two main entry points to these classes: registerService and getService. They are called
///during constructing of AcmDatumStd. Each service object contains a back pointer to enable it to remove
///its reference if these services are deleted. These services are used internally by AcmDatumStd to draw 
///specific types of datum targets.</summary>
class AcmCTargetService 
{
public:
  ///<summary>Destructures the AcmCTargetService class.</summary>
  virtual ~AcmCTargetService();
  virtual Acm::TargetType serviceType() const = 0;  
  ///<param name="mTransform">Specifies where the graphic representation of the symbol should be transformed.
  ///The sub-entities are created according to this matrix and cannot easily be transformed later.</param>
  virtual void getSubEnts(const AcmCSubSymbol* pData,
                          AcmCAuxEntArray& subEnts,
                          const AcGeMatrix3d& mTransform) const = 0;  

};                      
///<summary>This is class AcmCTargetBalloonService.</summary>
class AcmCTargetBalloonService : public AcmCTargetService 
{
public:
  virtual double radius() const = 0;
  virtual AcGePoint3d defaultSizePosition() const = 0;
  virtual double gapMultiple() const = 0;

protected:
  virtual void   drawOutside(const AcGePoint3d& p1,
                             const AcGePoint3d& p2,
                             AcDbMText& pText,
                             AcmCAuxEntArray& subEnts,
                             bool bMovable = false) const = 0;
};                      

inline 
AcmCTargetService::~AcmCTargetService()
{
}

#endif
