//////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2025 Autodesk, Inc.  All rights reserved.
//
//  Use of this software is subject to the terms of the Autodesk license 
//  agreement provided at the time of installation or download, or which 
//  otherwise accompanies this software in either electronic or hard copy form.   
//
//////////////////////////////////////////////////////////////////////////////
#ifndef __NOTESYM_H
#define __NOTESYM_H

class AmdtCNoteImp;
class AmdtCNoteList;
class AmdtNote;
#include "NoteStd.h"

///<summary>The AmdtCNote class - derived from the AcmCSubSymbol class.</summary>
class AmdtCNote : public AcmCSubSymbol {
public:
  AmdtCNote(AmdtNote* pSym);
  virtual ~AmdtCNote();

  Adesk::Boolean operator==(const AmdtCNote&) const;
  //virtual AmdtCNote& operator=(const AmdtCNote&);
  virtual AmdtCNote* clone()const;

  AmdtCNoteImp* getImp() const { return mpImp; }

  virtual AcDbMText& getNoteText(void) const;
  virtual void setNoteText(const AcDbMText& parText);
  virtual void mirrorTextLocation(AcGeVector3d xDir, AcGeVector3d yDir);
  virtual int mirrorTextAttachment(AcGeVector3d xDir, AcGeVector3d yDir,
                                   bool bNeed = false);
  virtual void setCacheValue(LPCTSTR value);
  virtual CString cacheValue() const;
  virtual void setAttachPoint(const AmdtNoteStd::attachPoint point);
  virtual AmdtNoteStd::attachPoint attachPoint() const;
  virtual AcArray<Adesk::Int32> templateType() const;
  virtual void setTemplateType(const AcArray<Adesk::Int32>& tempType);
  virtual void regenDimStyleIds();
  virtual AcGePoint3dArray& textBoundingPoints();
  virtual void setTextBoundingPoints(const AcGePoint3dArray& points);
  virtual AcmCLeader * leader(void) const;
  virtual void setTextAlign(const AmdtNoteStd::textAlignment align);
  virtual AmdtNoteStd::textAlignment textAlign() const;
  virtual AmdtNote* getOwner()const;

  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;

private:
    AmdtCNoteImp* mpImp{ nullptr };
};

///<summary>Class for Note Symbol.</summary>
class ACMSYMBB_CRX_DLLSHARE AmdtNote : public AcmSymbol {
  friend class AcmNoteTranslate;     
  friend class AmNoteIPE;
public:
  ACRX_DECLARE_MEMBERS(AmdtNote);
  AmdtNote();
  virtual ~AmdtNote();

  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*);
  virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;
  virtual Acad::ErrorStatus subErase(Adesk::Boolean erasing);

  virtual Acm::ErrorStatus setSymbolDefaults(AcDbDatabase *pDb = NULL);
  ///<summary>Sends a notification if the tip point of the leader has changed.</summary>
  virtual void leaderTipPointChanged(const AcGeVector3d& offset,
                                     const AcmCLeader* leader);
  ///<summary>Sets the scale factor for all sub-symbols (excluding leader).</summary>
  virtual void setScale(double scale);
  ///<summary>Provides the method for removing the nth- leader in the list.</summary>
  ///<param name="index">Specifies the index in the leader array. If the leader doesn't exist, the function returns eInvalidInput.</param>
  virtual Acm::ErrorStatus removeLeader(Adesk::UInt16 index);
  ///<summary>This function is called during the updating of symbols that takes place when the standard is changed.</summary>
  virtual void regen();
  virtual void setOrigin(const AcGePoint3d &origin);

  ///<summary>Detaches a geometry reference and frees it from memory.</summary>
  virtual Acm::ErrorStatus detachGeomRef();

  ///<summary>Attaches a geometry reference. 
  ///This function returns Adesk::kFalse if there is a geometry reference attached to the symbol already. 
  ///In that case you need to use the leader iterator and specify more precisely to which arrowhead they want to attach the geometry.</summary>
  ///<param name="pGeomRef"></param>
  ///<param name="viewId">Optional. 
  ///If without the view Id, this function is used to create the geometry association in model space. 
  ///The void pointer is the pointer to the MCAD API geometry key.</param>
  ///<param name="arrowheadLocation"></param>
  virtual Acm::ErrorStatus attachGeomRef(const void* pGeomRef,
                                         const AcDbObjectId &viewId,
                                         const AcGePoint3d &arrowheadLocation);

  ///<summary>Attaches a geometry reference. 
  ///This function returns Adesk::kFalse if there is a geometry reference attached to the symbol already. 
  ///In that case you need to use the leader iterator and specify more precisely to which arrowhead they want to attach the geometry.</summary>
  virtual Acm::ErrorStatus attachGeomRef(const void* pGeomRef,
                                         const AcGePoint3d &arrowheadLocation);
  AmdtCNote* subSymbol() const;
  void createNote(LPCTSTR productString);
  void createLanding(bool bNeeded = false);
  void setNewLanding(const AcGeVector3d & land);
  bool isLeftOriented() const;
  bool isLeftOriented(const AcGeVector3d& direction) const ;

  ///<summary>Set the alignment of the text.</summary>
  ///<param name="leftOriented">true if left-aligned, false if right-aligned</param>
  void setLeftOriented(bool leftOriented);

  bool isVerticalLanding();  

  ///<summary>Set the text in note symbol</summary>
  ///<param name="textStr">text string</param>
  void setNoteText(const ACHAR* textStr);

  ///<summary>Get the text in the note symbol. Return the non-evaluated text string.</summary>
  ACHAR* noteText(void) const;
  ///<summary>Get the evaluated text of variables and expressions in the note symbol.</summary>
  ACHAR* evaluatedNoteText(void) const;
  void setAttachPoint(const AmdtNoteStd::attachPoint point);
  AmdtNoteStd::attachPoint attachPoint() const;
  void setTextAlign(const AmdtNoteStd::textAlignment align); 
  AmdtNoteStd::textAlignment textAlign() const;
  bool set2dStructureView(const AcDbObjectId& viewId);
  void get2dStructureView(AcDbObjectId& viewId) const;
  void noteHighlight(Adesk::UInt16 num) const;
  void noteUnhighlight(Adesk::UInt16 num) const;
  ///<summary>Specifies which SubNote is the active SubNote. 
  ///Operations on the Note object which before had updated the sole SubNote now update the active SubNote.</summary>
  void SetSubNoteIndex(Adesk::UInt16 i);
  ///<summary>Returns the index of the active SubNote.</summary>
  Adesk::UInt16 GetSubNoteIndex();
  ///<summary>Inserts the supplied SubNote at the supplied index. If the index is negative, the SubNote is inserted at the front. 
  ///If the index is larger than the current number of SubNotes, the new SubNote is added at the end.</summary>
  Adesk::Boolean insertSubNoteAt(Adesk::UInt16 index, AmdtCNote* pSubNote);
  ///<summary>Removes the SubNote at the specified index. Incorrect index values are ignored.</summary>
  Adesk::Boolean removeSubNote(Adesk::UInt16 index);
  ///<summary>Returns the number of SubNotes in the Note symbol. Each branch in a multi-branch symbol has its own SubNote.</summary>
  Adesk::UInt16 numSubNotes() const;
  ///<summary>Returns a pointer to a new SubNote set up to be stylistically congruent with this Note symbol. 
  ///The new SubNote is not yet added to the list, so if it is not added via insertSubNoteAt, 
  ///it is the calling functions responsibility to free the allocated memory.</summary>
  AmdtCNote* newSubNote();
  ///<summary>Returns the width of the widest SubNote in the Note symbol.</summary>
  double getMaxWidth() const;
  ///<summary>Returns the flip status of the Note symbol. 
  ///False means the symbol extends to the right of the leader attach point, and True means the symbol extends to the left.</summary>
  bool getFlip() const;
  ///<summary>Sets the flip status of the Note symbol. 
  ///False means the symbol extends to the right of the leader attach point, and True means the symbol extends to the left.</summary>
  void setFlip(bool bFlip);

protected:
  virtual Adesk::Boolean    subWorldDraw(AcGiWorldDraw* wsg);
  ///<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;
  ///<summary>Lists all leaders including their vertices, standard name and original name, server name and version.</summary>
  virtual void              subList() const;
  ///<summary>Determines which sub-symbols or leaders belong to the GS marker. Then, it asks for sub-entities and applies getOsnapPoints to them.</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);

  virtual Acad::ErrorStatus subMoveGripPointsAt(const AcDbVoidPtrArray& gripAppData, 
                                              const AcGeVector3d& offset, 
                                              const int bitflags);
  virtual Acad::ErrorStatus subGetClassID(CLSID* pClsid) const;
  Acad::ErrorStatus subGetSubentPathsAtGsMarker(AcDb::SubentType     type,
                                             INT_PTR              gsMark,
                                             const AcGePoint3d&   pickPoint,
                                             const AcGeMatrix3d&  viewXform,
                                             int&                 numPaths,
                                             AcDbFullSubentPath*& subentPaths,
                                             int                  numInserts,
                                             AcDbObjectId*        entAndInsertStack) const;
  Acad::ErrorStatus subGetGsMarkersAtSubentPath(const AcDbFullSubentPath& path,
                                             AcArray<INT_PTR>& gsMarkers) const;

private:
  AmdtCNoteList *mpSubSymbol;
  bool mbFlip;
};
DBREF_DECLARE(AmdtNote)


#endif //__NOTESYM_H
