//////////////////////////////////////////////////////////////////////////////
//
//  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.
//
//////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef __SYMBOL_H
#error Include "symbol.h" before including this file
#endif

class AmdtEdge;
class AmdtCEdge;
class AmdtEdge;
class AmdtCEdgeImp;
class AcmSymbolStd;
class AmdtEdgeStdImp;
class AcmStringValue;

///<summary>The Edge Standard class. This class is derived from the AcmSymbolStd class.</summary>
class ACMSYMBB_CRX_DLLSHARE AmdtEdgeStd : public AcmSymbolStd
{
  friend class AcmSymbbInternals;
  friend class AcmStandardImp;
  friend class AmdtEdgeStdImp;
public:
  ACRX_DECLARE_MEMBERS(AmdtEdgeStd);
  ///<summary>the destruct function.</summary>
  virtual ~AmdtEdgeStd();
  const ACHAR* getBaseSymStdClassName() const override;
  Adesk::Boolean majorityAllowed() const;
  void setMajorityAllowed(Adesk::Boolean val);
  Adesk::Boolean fullList() const;
  void setFullList(Adesk::Boolean v);
  virtual Acm::ErrorStatus getDescription(CString& desc,
                                          CBitmap*& pBmpLoaded,
                                          CBitmap*& pBmpReg,
                                          Adesk::Boolean& enablePref) const;
  virtual Acm::ErrorStatus checkVisibility(AmdtCEdge* pData) const;
  virtual Acm::ErrorStatus setSuggested(AmdtCEdge *pSubSym) const;
  
  virtual void setDefaultSubSymbol(AmdtCEdge* pData) const;
  virtual Acm::ErrorStatus initFields(AmdtCEdge *pSubSym) const;
  virtual Acm::ErrorStatus validityFields(AmdtCEdge *pSubSym,
                                          bool setBoundary = false,
                                          int dlgIndex = -1);

  virtual Acm::ErrorStatus validityEdgeLimits(AmdtCEdge* pSubSym,
                                              Acm::Variable currVar,
                                              AcmStringValue& currLimit);

  virtual void getSubEnts(const AmdtCEdge* pSymb,
                          AcmCAuxEntArray& subents,
                          bool corrSymbOnRightSide = false) const;

  virtual void getLibSubEnts(const AmdtEdge* pEdge,
                             const AmdtCEdge* pSubSymb,
                             AcmCAuxEntArray& subents) 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>This is record AmdtEdgeStd::Variable.</summary>
  enum Variable {
    kBracketAllowed = 0,
    kFullList    
  };
  virtual Acm::Visibility variableStatus(AmdtEdgeStd::Variable var) const;
  virtual void setVariableStatus(AmdtEdgeStd::Variable var, Acm::Visibility status) const;
  virtual void getHeights(const AmdtCEdge*, AcGeDoubleArray&) const;
  Adesk::Boolean allAroundAllowed() const;
  void setAllAroundAllowed(Adesk::Boolean val);
  Adesk::Boolean stdNumAllowed() const;
  void setStdNumAllowed(Adesk::Boolean val);

  ///<summary>Get the suggested values list for edge.</summary>
  ///<param name="strList">suggest values string list.</param>
  virtual Acm::ErrorStatus getSuggestedList(CStringList& strList) const;

  ///<summary>Get the list avalable type for undefined direction </summary>
  ///<param name="List">vector of the value represented by Acm::EdgeUndefinedDirection enum.</param>
  ///<returns>Returns Acm::eOK for succes </returns>
  virtual Acm::ErrorStatus getUndefinedSizePosList(std::vector<Adesk::UInt16>& list) const;

  ///representation for the revision.
  ///<summary>It returns true if the edge symbol is drawn above the arrow landing.</summary>
  virtual bool isSymAboveLanding() const;

  ///<summary>Get the list avalable type for edge sign</summary>
  ///<param name="List">vector of the value represented by Acm::EdgeSignType enum.</param>
  ///<returns>Returns Acm::eOK for succes </returns>
  virtual Acm::ErrorStatus getEdgeSignTypeList(std::vector<Adesk::UInt16>& list) const;

  ///<summary>Get the list avalable type for options </summary>
  ///<param name="List">vector of the value represented by Acm::EdgeOptionsType enum.</param>
  ///<returns>Returns Acm::eOK for succes </returns>
  virtual Acm::ErrorStatus getOptionsList(std::vector<Adesk::UInt16>& list) const;

  ///<summary>Get the list avalable position for indication directions </summary>
  ///<param name="List">vector of the value represented by Acm::EdgeDirectionType enum.</param>
  ///<returns>Returns Acm::eOK for succes </returns>
  virtual Acm::ErrorStatus getDirectionList(std::vector<Adesk::UInt16>& list) const;

  ///<summary>Sets the default values for prefix sufix strings of variables in edge sub-symbol</summary>
  virtual Acm::ErrorStatus initPost(AmdtCEdge* pSubSym) const;

  ///<summary>Gets the tool tip string for given edge sub-symbol</summary>
  virtual Acm::ErrorStatus getTooltip(const AmdtCEdge* pSubSym, CString& resStr) const;

  ///<summary> return gdt Style object ID</summary>
  AcDbObjectId gdtStyleId() const;
  ///<summary>Sets the Id of the special font for GDT symbols.</summary>
  void setGdtStyleId(const AcDbObjectId& id);

  Acad::ErrorStatus createDefaultStyle(LPCTSTR styleName, LPCTSTR fontName);

  ///<summary>Sets the factory default values.</summary>
  virtual Adesk::Boolean setFactoryDefaults() override;

protected:
  AmdtEdgeStd();
  virtual void getMajoritySymbol(const AmdtCEdge* pSubSym,
                                 AcmCAuxEntArray& subents) const;
  virtual void getLeaderSymbol(const AmdtCEdge* pSubSym,
                               AcmCAuxEntArray& subents) const;
  virtual Acad::ErrorStatus subGetClassID(CLSID* pClsid) const;

private:
  AmdtEdgeStdImp* mpImp;
};
DBREF_DECLARE(AmdtEdgeStd)

///<summary>The AmdtCEdge class - derived from the AcmCSubSymbol class.</summary>
class AmdtCEdge : public AcmCSubSymbol
{
public:

  AmdtCEdge(AmdtEdge*);
  virtual ~AmdtCEdge();

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

  Adesk::Boolean operator==(const AmdtCEdge&) const;
  Adesk::Boolean isEqual(const AmdtCEdge&) const;

  virtual AmdtCEdge& operator=(const AmdtCEdge&);
  AmdtCEdge* clone()const;

  virtual Adesk::Boolean isMajority() const;

  virtual Acm::Direction leaderDirection(Acm::Direction singularity = Acm::kToTop, 
                                         AcGePoint3d peak = AcGePoint3d::kOrigin) const;

  virtual Adesk::Boolean isAllAround(bool bCheckVisibility = false) const;
  virtual Acm::ErrorStatus setAllAround(Adesk::Boolean flag);

  virtual Adesk::Boolean newSymbolRev() const;
  virtual Acm::ErrorStatus setNewSymbolRev(Adesk::Boolean newRev = Adesk::kTrue);

  virtual Adesk::Boolean isStdNum(bool bCheckVisibility = false) const;
  virtual Acm::ErrorStatus setStdNum(Adesk::Boolean flag);

  virtual Adesk::Boolean isLimitedArea(bool bCheckVisibility = false) const;
  ///<summary>It sets whether or not the direction of undefined size is set.</summary>
  virtual Acm::ErrorStatus setLimitedArea(bool flag);

  ///<summary>It returns if the edge symbol indication of Quantity.</summary>
  ///<returns>bool.</returns>
  virtual Adesk::Boolean isQuantity(bool bCheckVisibility = false) const;
  ///<summary>It sets whether or not the Quantity of indication is set.</summary>
  virtual Acm::ErrorStatus setQuantity(bool flag);

  virtual Acm::EdgeOptionsType edgeOption() const;
  virtual Acm::ErrorStatus setEdgeOption(Acm::EdgeOptionsType value);

  virtual Acm::EdgeDirectionType directionPos() const;
  virtual Acm::ErrorStatus setDirectionPos(Acm::EdgeDirectionType value);

  virtual const AcmStringValue& edgeMax() const;
  virtual const AcmStringValue& edgeMin() const;
  virtual const AcmStringValue& edgeSign() const;

  virtual const AcmStringValue& edgeAsMax() const;
  virtual const AcmStringValue& edgeAsMin() const;

  virtual const AcmStringValue& edgeIdFrom() const;
  virtual const AcmStringValue& edgeIdTo() const;
  virtual const AcmStringValue& edgeQuantity() const;

  ///<summary>It returns true if the undefined size is allowed.</summary>
  virtual bool isUndefinedSize(bool bCheckVisibility = false) const;
  ///<summary>This sets whether or not the undefined size of the edge symbol is allowed.</summary>
  virtual Acm::ErrorStatus setUndefinedSize(bool flag);

  ///<summary>It returns true if the direction of undefined size is set.</summary>
  virtual bool isDefinedDirect(bool bCheckVisibility = false) const;
  ///<summary>It sets whether or not the direction of undefined size is set.</summary>
  virtual Acm::ErrorStatus setDefinedDirect(bool flag);  

  ///<summary>It returns the direction of undefined size.</summary>
  ///<returns>The return value can be any member of enum Acm::EdgeUndefinedDirection.</returns>
  virtual Acm::EdgeUndefinedDirection undefinedDirection() const;
  ///<summary>Set the direction of undefined size.</summary>
  ///<param name="direct">Input Only.Can be any member of enum Acm::EdgeUndefinedDirection.</param>
  virtual Acm::ErrorStatus setUndefinedDirection(Acm::EdgeUndefinedDirection direct);

  virtual AcmValue* property(Acm::Variable var) const;

  ///<summary>Gets the origin of the symbol in WCS.</summary>
  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;

  void setVerSchema(Adesk::UInt16 ver);


  AmdtCEdgeImp* getImp() { return mpImp; };
  const AmdtCEdgeImp* getImp() const { return mpImp; };

private:
    AmdtCEdgeImp* mpImp { nullptr };
};

///<summary>Class for Note Symbol.</summary>
class ACMSYMBB_CRX_DLLSHARE AmdtEdge : public AcmSymbol
{
    friend class CLeaderPage;
public:
    ACRX_DECLARE_MEMBERS(AmdtEdge);
    ///<summary>The construct function.</summary>
    AmdtEdge();
    ///<summary>The destruct function.</summary>
    virtual ~AmdtEdge();

    AmdtCEdge* subSymbol();
    const AmdtCEdge* subSymbol() 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);
    virtual Acm::ErrorStatus setSymbolDefaults(AcDbDatabase* pPropertiesDb = NULL);
    virtual AmdtCEdge* newSubEdge() const;

    virtual Adesk::Boolean isMajority() const;
    virtual Acm::ErrorStatus setMajority(const Adesk::Boolean);

    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;
    ///<summary>Sends a notification if the tip point of the leader has changed.</summary>
    virtual void leaderTipPointChanged(const AcGeVector3d&, const AcmCLeader*);
    virtual Adesk::Boolean getAdditionalEnts(AcmCAuxEntArray& subents) const;
    ///<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);
    virtual Adesk::Boolean isAllAround() const;
    virtual Acm::ErrorStatus setAllAround(Adesk::Boolean flag);
    virtual Acm::ErrorStatus setNewSymbolRev(Adesk::Boolean newRev = Adesk::kTrue);
    virtual Adesk::Boolean newSymbolRev() const;
    virtual Adesk::Boolean isStdNum() const;
    virtual Acm::ErrorStatus setStdNum(Adesk::Boolean flag);

    ///<summary>It returns true if the undefined size is allowed.</summary>
    virtual bool isUndefinedSize() const;
    ///<summary>This sets whether or not the undefined size of the edge symbol is allowed.</summary>
    virtual Acm::ErrorStatus setUndefinedSize(bool flag);

    ///<summary>It returns true if the direction of undefined size is set.</summary>
    virtual bool isDefinedDirect() const;
    ///<summary>It sets whether or not the direction of undefined size is set.</summary>
    virtual Acm::ErrorStatus setDefinedDirect(bool flag);

    ///<summary>It returns the direction of undefined size.</summary>
    ///<returns>The return value can be any member of enum Acm::EdgeUndefinedDirection.</returns>
    virtual Acm::EdgeUndefinedDirection undefinedDirection() const;
    ///<summary>Set the direction of undefined size.</summary>
    ///<param name="direct">Input Only.Can be any member of enum Acm::EdgeUndefinedDirection.</param>
    virtual Acm::ErrorStatus setUndefinedDirection(Acm::EdgeUndefinedDirection direct);

    ///<summary>It returns major type of edge apearence.</summary>
    ///<returns>Acm::EdgeOptionsType.</returns>
    virtual Acm::EdgeOptionsType edgeOption() const;
    ///<summary>It sets major type of edge apearence.</summary>
    virtual Acm::ErrorStatus setEdgeOption(Acm::EdgeOptionsType value);

protected:
    virtual Adesk::Boolean    subWorldDraw(AcGiWorldDraw* pMode);
    ///<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&, const AcGeVector3d&);

    virtual Acad::ErrorStatus subMoveGripPointsAt(const AcDbVoidPtrArray& gripAppData,
        const AcGeVector3d& offset,
        const int bitflags);
    ///<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>Sums geometry extents for a leader.</summary>
    virtual Acad::ErrorStatus subGetGeomExtents(AcDbExtents& extents) const;
    virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d& xform);
    virtual Acad::ErrorStatus subGetClassID(CLSID* pClsid) const;

private:
    AmdtCEdge* mpSubSymbol;
};
DBREF_DECLARE(AmdtEdge)