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

#include "AdAChar.h"

class AcmCFCF;
class AcmCFCFImp;
class AcmFCFStdImp;
class AcmFCF;
class AcmCfcfImpSymbolISO;
///<summary>This class is responsible for the FCF sub-symbol and implements all of its virtual member functions.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmFCFStd : public AcmSymbolStd
{
  friend class AcmSymbbInternals;
public:
  ACRX_DECLARE_MEMBERS(AcmFCFStd);
  virtual ~AcmFCFStd();
  virtual Acm::ErrorStatus getDescription(CString& desc,
                                          CBitmap*& pBmpLoaded,
                                          CBitmap*& pBmpReg,
                                          Adesk::Boolean& enablePref) const;
  const ACHAR* getBaseSymStdClassName() const override;
  ///<summary>Gets the Id of the special font for GDT symbols.</summary>
  AcDbObjectId gdtStyleId() const;
  ///<summary>Sets the Id of the special font for GDT symbols.</summary>
  void setGdtStyleId(const AcDbObjectId& id);

  Acad::ErrorStatus setGdtStyleName(LPCTSTR value);
  ///<summary>Gets the font style name for GDT symbols.</summary>
  Acad::ErrorStatus getGdtStyleName(CString& name,CString& font) const;
  ///<summary>Gets the font name for GDT symbols.</summary>
  Acad::ErrorStatus getGdtFontName(const ACHAR*& fontName) const;
  Acad::ErrorStatus setGdtFontName(LPCTSTR value);
  ///<summary>Gets the gap between the frame and text inside the symbol.</summary>
  double frameGap() const;
  ///<summary>Sets the gap between the frame and text inside the symbol.</summary>
  void setFrameGap(double value);
  ///<summary>Gets the status for end padding, that is, if both rows are not same length, whether symbol
  ///frame is shortened or not.</summary>
  Adesk::Boolean endPadding() const;
  ///<summary>Sets the status for end padding, that is, if both rows are not same length, whether symbol
  ///frame is shortened or not.</summary>
  void setEndPadding(Adesk::Boolean value);
  ///<summary>Gets whether identical symbols used in the symbol will be expressed as one or two symbols.</summary>
  Adesk::Boolean mergeSymbol() const;
  ///<summary>Sets whether identical symbols used in the symbol will be expressed as one or two symbols.</summary>
  void setMergeSymbol(Adesk::Boolean value);
  ///<summary>Gets whether two identical tolerances or datums used in the symbol will be expressed as one 
  ///or two text strings.</summary>
  Adesk::Boolean mergeTolerance() const;
  ///<summary>Sets whether two identical tolerances or datums used in the symbol will be expressed as one
  ///or two text strings.</summary>
  void setMergeTolerance(Adesk::Boolean value);
  ///<summary>Gets whether two identical symbols, tolerances, or datums used in the symbol will be expressed
  ///as one or two symbols.</summary>
  Adesk::Boolean mergeDatum() const;
  ///<summary>Gets state if we draw the FCf frame with the square shape style in case for minimal size of internal frames</summary>
  Adesk::Boolean squareFrame() const;

  ///<summary>Sets whether two identical symbols, tolerances, or datums used in the symbol will be expressed
  ///as one or two symbols.</summary>
  void setMergeDatum(Adesk::Boolean value);

  ///<summary>Sets state if we draw the FCf frame with the square shape style in case for minimal size of internal frames.</summary>
  void setSquareFrame(Adesk::Boolean value);

  ///<summary>Gets whether projected tolerance is in line or not.</summary>
  Adesk::Boolean separateProjected() const;
  ///<summary>Sets whether projected tolerance is in line or not.</summary>
  void setSeparateProjected(Adesk::Boolean value);
  ///<summary>Gets whether datum can be on last line, separated from the tolerance value.</summary>
  Adesk::Boolean separateDatumId() const;
  ///<summary>Sets whether datum can be on last line, separated from the tolerance value.</summary>
  void setSeparateDatumId(Adesk::Boolean value);
  ///<summary>Gets the auxiliary symbols that will be visible in standard setting dialog.</summary>
  void getOfferedAuxSymbols(AcDbIntArray& array) const;
  ///<summary>Sets the auxiliary symbols that will be visible in standard setting dialog.</summary>
  void setOfferedAuxSymbols(const AcDbIntArray& array);
  ///<summary>Gets the special GDT symbols that will be visible in standard setting dialog.</summary>
  void getOfferedGdtSymbols(AcDbIntArray& array) const;
  ///<summary>Sets the special GDT symbols that will be visible in standard setting dialog.</summary>
  void setOfferedGdtSymbols(const AcDbIntArray& array);
  ///<summary>Returns the list of available geometric characteristic descriptor objects.</summary>
  virtual Adesk::Boolean getGeom(AcmCObjArray<AcmCGDTSymbolDesc>& list,
                                 const AcmCFCF* pSubSym = NULL) const;
  ///<summary>Returns the list of available plane and feature indicator descriptor objects.</summary>
  virtual Adesk::Boolean getPlaneAndFeatDescs(AcmCObjArray<AcmCGDTIndicatorDesc>& list,
      const AcmCFCF* pSubSym = NULL) const;
  ///<summary>Sets the list of allowed geometric characteristic symbols.</summary>
  virtual Adesk::Boolean setGeom(const AcmCObjArray<AcmCGDTSymbolDesc>& list);
  ///<summary>Returns the list of available material removal characteristics.</summary>
  virtual Adesk::Boolean getMat(AcmCObjArray<AcmCGDTSymbolDesc>& list) const;
  ///<summary>Sets the list of allowed material removal characteristic symbols.</summary>
  virtual Adesk::Boolean setMat(const AcmCObjArray<AcmCGDTSymbolDesc>& list);
  ///<summary>Converts the GDT symbol type to its string representation.</summary>
  virtual Adesk::Boolean getSymbolImp(int subSym,
                                      CString& symtext) const;
  ///<summary>Converts the GDT symbol type to its string representation.</summary>
  virtual Adesk::Boolean getSymbolImp(Acm::GdtSymbolType subSym,
                                      CString& symtext) const;
  void initToEditOriginal()const override;
  void initToEdit()const override;
  ///<summary>Get the list of all arrowheads or all standard-supported arrowheads for the FCF symbol std. It
  ///will return additional arrowheads on top of those available in AcmSymbolStd.</summary>
  Adesk::Boolean getArrowDesc(AcmCObjArray<AcmCArrowDesc>& list,
                              Adesk::Boolean allSrv = Adesk::kTrue,
                              Adesk::Boolean bDarkTheme = Adesk::kFalse) const override;
  ///<summary>Sets the factory default values.</summary>
  virtual Adesk::Boolean setFactoryDefaults();
  ///<summary>Initializes the sub-symbol.</summary>
  virtual void setDefaultSubSymbol(AcmCFCF* pData) const;
  ///<summary>Checks whether the symbol data is visible or not.</summary>
  virtual Acm::ErrorStatus checkVisibility(AcmCFCF* pData) const;
  ///<summary>Set default (hidden) visibility of the symbol data.</summary>
  virtual Acm::ErrorStatus setDefaultVisibility(AcmCFCF* pSubSym) const;
  ///<summary>Initializes the default GUI values for FCF symbol variables.</summary>
  virtual Acm::ErrorStatus initDefaultFields(AcmCFCF* pData) const;
  ///<summary>Initializes the feature control frame symbol.</summary>
  virtual Acm::ErrorStatus initFields(AcmCFCF* pData) const;
  ///<summary>Sets the suggested values for any value in the sub-symbol.</summary>
  virtual Acm::ErrorStatus setSuggested(AcmCFCF* pData) const;
  ///<summary>Creates a list of all sub-entities, which represents the symbol according the content of sub-symbol.</summary>
  ///<param name="secondLeaderPoint">If specified, this function will be filled with the second point to 
  ///attach leader to.</param>
  ///<param name="pTopBoundingLine">If specified, this function will be filled with the top line of the boundary 
  ///<param name="pBottomBoundingLine">If specified, this function will be filled with the bottom line of the boundary 
  virtual void getSubEnts(const AcmCFCF* pSymb, AcmCAuxEntArray& subents, AcGePoint3d* pSecondLeaderPnt = NULL, 
                          AcGeLineSeg3d* pTopBoundingLine = NULL, AcGeLineSeg3d* pBottomBoundingLine = NULL) const;

  ///<summary>Function returns  a list of all sub-entities, which represents the symbol according the content of sub-symbol.
  /// The entities are transformed to final position in the symbol UCS according to input state bMTextAttached.
  /// Function additionally returns the sub entities transformation matrix for symbol UCS</summary>
  ///<param name="pSubSym"> pointer to0 FCF sub-entity </param>
  ///<param name="subents"> out list of all graphic sub-entities </param>
  ///<param name="bMTextAttached"> State if the symbol is attached to Mtext - it affect finnal transformation </param>
  ///<param name="mat"> output transformation matrix which was aplied on the sub-entities list </param>
  virtual void getSubEntsTransMat(const AcmCFCF* pSubSym, bool bMTextAttached,
                                  AcmCAuxEntArray& subents, AcGeMatrix3d& mat) const;

  ///<summary>Gets the sub-entities for the all-around symbol.</summary>
  virtual void getSubEntsAllAround(AcmCAuxEntArray& subents, Acm::SurfTextAppModifierType flag,
                                   const AcGeMatrix3d& mat) const;

  ///<summary>Function returns  a list of sub-entities, which represents the landing line of sub-symbol.
  /// It is case if the symbol draws own landing line because the leader is not present 
  ///<param name="subents"> in/out list of all graphic sub-entities </param>
  ///<param name="mat"> output transformation matrix which should be aplied on next added sub-entities</param>
  virtual void getSubEntsOfLandingLine(AcmCAuxEntArray& subents, AcGeMatrix3d& mat) 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 AcmFCFStd::Variable.</summary>
  enum Variable {
    kMergeSymbol = 0,
    kMergeTolerance,
    kMergeDatums,
    kEndPadding,
    kGDTStyle,
    kSepProjected,
    kSepDatumId,
    kInLineNotes,
    kPFIndicator,
    kSquareFrame
  };

  ///<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>
  ///<param name="var">It can be can be kMergeSymbol, kMergeTolerance, kMergeDatums, kEndPadding, kGDTStyle, 
  ///kSepProjected, kInLineNotes, kPFIndicator ,kSepDatumId or kSquareFrame.</param>
  virtual Acm::Visibility variableStatus(AcmFCFStd::Variable var) const;

  ///<summary>Sets the visibility status of the editing controls.</summary>
  ///<param name="var">It can be can be kMergeSymbol, kMergeTolerance, kMergeDatums, kEndPadding, kGDTStyle, 
  ///kSepProjected, kInLineNotes, kPFIndicator ,kSepDatumId or kSquareFrame.</param>
  ///<param name="status">It can be kHidden, kDisabled, kShaded, kSelectOnly, kVisible, where kDisabled, kShaded 
  ///and kSelectOnly have the same meaning.</param>
  virtual void setVariableStatus(AcmFCFStd::Variable var, Acm::Visibility status) const;

  ///<summary>Indicates whether or not the symbol has a landing that connects the leader to the symbol.</summary>
  ///<returns>Adesk::kTrue (default), or Adesk::kFalse</returns>
  virtual Adesk::Boolean isLandingAllowed() const;
  ///<summary>This function is used to return the default secondary arrow type for symbol.</summary>
  virtual Acm::ArrowType defaultSecondaryArrowType() const;

  ///<summary>Returns true if this symbol standard supports surface indication leader. 
  ///Otherwise, returns false.</summary>
  Adesk::Boolean isSurfIndLeaderSupported() const override;
  ///<summary>Gets the surface indication leader's arrow scale.</summary>
  double surfIndLeaderArwScale() const override;
  ///<summary>Sets the surface indication leader's arrow scale.</summary>
  ///<param name="scale">New arrow scale to set. It should be above zero.</param>
  Acm::ErrorStatus  setSurfIndLeaderArwScale(double scale) override;
  ///<summary>Gets the surface indication leader's arrow scale ByStandard status.</summary>
  Adesk::Boolean    surfIndLeaderArwScaleByStandard() const override;
  ///<summary>Sets the surface indication leader's arrow scale ByStandard status.</summary>
  ///<param name="byStandard">New ByStandard state to set.</param>
  Acm::ErrorStatus  setSurfIndLeaderArwScaleByStandard(Adesk::Boolean byStandard) override;
  ///<summary>Gets the surface indication leader's arrow type.</summary>
  Acm::ArrowType    surfIndLeaderArwType() const override;
  ///<summary>Sets the surface indication leader's arrow type.</summary>
  ///<param name="type">New arrow type to set.</param>
  Acm::ErrorStatus  setSurfIndLeaderArwType(Acm::ArrowType type) override;
  ///<summary>Gets the surface indication leader's arrow type ByStandard status.</summary>
  Adesk::Boolean    surfIndLeaderArwTypeByStandard() const override;
  ///<summary>Sets the surface indication leader's arrow type ByStandard status.</summary>
  ///<param name="byStandard">New ByStandard state to set.</param>
  Acm::ErrorStatus  setSurfIndLeaderArwTypeByStandard(Adesk::Boolean byStandard) override;

  ///<summary>Gets the information about allowance all-around symbol.</summary>
  Adesk::Boolean allAroundAllowed() const;
  ///<summary>Sets the information about allowance all-around symbol.</summary>
  void setAllAroundAllowed(Adesk::Boolean val);

  ///<summary>Gets the information about allowance plane and feature symbol indicator.</summary>
  Adesk::Boolean isPFIndicatorAllowed() const;
  ///<summary>Sets the information about allowance plane and feature symbol indicator.</summary>
  void setPFIndicatorAllowed(Adesk::Boolean val);

  ///<summary>Gets the information about allowance InLine Notes symbol property.</summary>
  Adesk::Boolean inLineNotesAllowed() const;
  ///<summary>Sets the information about allowance InLine Notes symbol property.</summary>
  void setInLineNotesAllowed(Adesk::Boolean val);

  ///<summary> return true when the multi row descriptor is enabled in the FCF sub-symbol</summary>
  virtual Adesk::Boolean allowedMultiRowDesc() const;
  ///<summary> return true when the multi Indicator descriptor is enabled in the FCF sub-symbol</summary>
  virtual Adesk::Boolean allowedMultiIndicatorDesc() const;

  ///<summary>Returns true if this leader line will attach to the center of frame. 
  ///Otherwise, returns false.</summary>
  virtual Adesk::Boolean leaderPos() const;
  ///<summary>Sets leader line's attach position.</summary>
  ///<param name="leaderPos">New leader position to set.</param>
  Acm::ErrorStatus  setLeaderPos(Adesk::Boolean leaderPos);

  Adesk::Boolean setSurfIndLeaderFactoryDefaults() override;

  ///<summary>Gets a SurfText application modifiers types list.</summary>
  virtual std::vector <Acm::SurfTextAppModifierType> getStAppModifierTypeList() const;

  ///<summary>Gets available types of attach position for reference line and symbol geometric specification</summary>
  virtual std::vector <Acm::FCFAttachmentPoint> getRefLineAttachPositionList() const;

  ///<summary>Gets default type of attach position between reference line and symbol geometrical specification</summary>
  virtual Acm::FCFAttachmentPoint refLineAttachPosition() const;

  ///<summary>Gets avalable types of place and feature indicartor types</summary>
  virtual std::vector <Acm::GdtIndicatorType> getPlaceAndFeatureIndicatorList() const;

  ///<summary>Gets default type of of place and feature indicartor</summary>
  virtual Acm::GdtIndicatorType placeAndFeatureIndicator() const;

  /// <summary>
 /// Function returns keyword and prompt for particular taper descriptor.
 /// </summary>
 /// <param name="desc"> descriptor of taper type</param>
 /// <param name="prompt"> output prompt for CLI or OPM</param>
 /// <param name="keyword"> output keyword for CLI </param>
 /// <param name="bCLVersion"> desides if we return the prompt for CLI or OPM </param>
 ///
  virtual void getPromptKeyword(const AcmCGDTSymbolDesc& desc, Adesk::UInt64& prompt, AcString& keyword, bool bCLVersion = true) const;
  virtual void getSymbolType(const AcmCFCF* pSubSym, const AcString& keyword, Acm::GdtSymbolType& type);
  virtual void getKeywordFromType(const Acm::GdtSymbolType type, const AcmCFCF* pSubSym, AcString& keyword);

  //////////////////////////////////////////////////////////////////////////
  //helper functions to draw multi row FCF graphic
  virtual void getSubEnts4Multiline(const AcmCFCF* pSubSym,
                            AcmCAuxEntArray& subents,
                            AcmCfcfImpSymbolISO* pFcfDrawEngine,
                            AcGePoint3d* pSecondLeaderPnt/*=NULL*/,
                            AcGeLineSeg3d* pTopBoundingLine /*= NULL*/,
                            AcGeLineSeg3d* pBottomBoundingLine /*= NULL*/) const;

  virtual void getSubEntsTransMat4Multiline(const AcmCFCF* pSubSym,
                                            bool bMTextAttached,
                                            AcmCAuxEntArray& subents,
                                            AcGeMatrix3d& mat,
                                            AcmCfcfImpSymbolISO* pFcfDrawEngine) const;

  virtual void getSubEntsAllAround_3Opt(AcmCAuxEntArray& subents, Acm::SurfTextAppModifierType flag,
                                        const AcGeMatrix3d& mat) const;
  private:
  //helper methods
  static AcGeVector3d vectorToLeaderPosISO(AcmCfcfImpSymbolISO* pFcfDrawEngine, int leaderStatus, Acm::FCFAttachmentPoint attachType, bool bLeaderPos);
  static AcGePoint3d secondLeaderPointISO2017(AcmCfcfImpSymbolISO* pFcfDrawEngine, int leaderStatus, Acm::FCFAttachmentPoint attachType, bool bLeaderPos);

protected:
  AcmFCFStd();
  Acad::ErrorStatus createDefaultStyle(LPCTSTR styleName, LPCTSTR fontName);
  virtual Acad::ErrorStatus   subGetClassID(CLSID* pClsid) const;

  ///<summary>Gets the start and end points of the sub-symbol landing line.</summary>
  virtual void getLandingLinePoints(AcmCAuxEntArray& subents, AcGePoint3d& startPt, AcGePoint3d& endPt) const;

private:
  AcmFCFStdImp *mpImp;
};
DBREF_DECLARE(AcmFCFStd)

///<summary>This symbol does not have an extended interface implemented. The basic interface is implemented as
///described in AcmCSubSymbol.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmCFCF : public AcmCSubSymbol
{
public:

    AcmCFCF(AcmFCF* pSymbol);
    virtual ~AcmCFCF();

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

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

    Adesk::Boolean operator==(const AcmCFCF&) const;

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

    //AcmCSubSymbol
    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;


  ///<summary>Gets the symbol type information for the two symbols.</summary>
  virtual Acm::GdtSymbolType symbol() const;
  ///<summary>Sets the symbol type information for the two symbols.</summary>
  virtual void setSymbol(Acm::GdtSymbolType sym);
  ///<summary>Gets the list of integers representing the allowed values of symbol types.</summary>
  virtual void getSymbolAllowedList(AcDbIntArray& arr) const;
  ///<summary>Sets the list of integers representing the allowed values of symbol types.</summary>
  virtual void setSymbolAllowedList(const AcDbIntArray& arr);

  virtual Acm::GdtSymbolType symbol2() const;
  virtual void setSymbol2(Acm::GdtSymbolType sym);
  ///<returns>This function is only used for GOST standard.</returns>
  virtual Acm::GdtSymbolType symbol3() const;
  ///<summary>Sets the GDT symbol type for the 3rd row.</summary>
  virtual void setSymbol3(Acm::GdtSymbolType sym);

  ///<summary>Gets where the leader is connected.</summary>
  virtual Adesk::UInt8 leaderStatus() const;

  virtual const AcmCObjArray<AcGeLineSeg3d>& getBoundingLines() const;

  virtual void purge(bool all = false);

  //////////////////////////////////////////////////////////////////////////
  //New interface 
  ///<summary>Gets the value of any symbol variable and given row/column.</summary>
  virtual LPCTSTR tableValue(Acm::Variable var, Adesk::UInt16 rowIdx, Adesk::UInt16 columnIdx) const;
  ///<summary>Gets the value of any symbol variable and given row/column.</summary>
  virtual Acm::ErrorStatus getTableValue(Acm::Variable var, Adesk::UInt16 rowIdx, Adesk::UInt16 columnIdx, CString& value) const;
  ///<summary>Sets the value of any symbol variable and given row/column.</summary>
  virtual Acm::ErrorStatus setTableValue(Acm::Variable var, Adesk::UInt16 rowIdx, Adesk::UInt16 columnIdx, LPCTSTR value);
  ///<summary>Gets the visibility status of the given symbol variable and row/column.</summary>
  virtual Acm::Visibility  tableVariableStatus(Acm::Variable var, Adesk::UInt16 rowIdx, Adesk::UInt16 columnIdx) const;
  ///<summary>Sets the visibility status of the given symbol variable and row/column.</summary>
  virtual Acm::ErrorStatus setTableVariableStatus(Acm::Variable var, Adesk::UInt16 rowIdx, Adesk::UInt16 columnIdx, Acm::Visibility status);
  ///<summary> Return state if the given property of sub-symbol supports multi-row symbol description.</summary>
  ///<returns>true if the sub-symbol supports the multi-rows.description</returns>
  virtual bool isSupportMultiRowsDesc(Acm::Variable var) const;
  ///<summary> Return state if the given property of sub-symbol supports values Table symbol description.</summary>
  ///<returns>true if the sub-symbol supports the values Table.description</returns>
  virtual bool isSupportTableDesc(Acm::Variable var) const;

  ///<summary> Return type of the indicator from the Plane and Feature indicator description.</summary>
  ///<returns>enum type GdtIndicatorType as Indicator type</returns>
  virtual Acm::GdtIndicatorType indicatorType() const;
  ///<summary> Set type of the indicator for the Plane and Feature indicator description.</summary>
  virtual void setIndicatorType(Acm::GdtIndicatorType type);

  ///<summary> Return type of the symbol from the Plane and Feature indicator description.</summary>
  ///<returns>enum type GdtSymbolType as symbol type</returns>
  virtual Acm::GdtSymbolType indicatorSymbolType() const;
  ///<summary> Set type of the symbol for the Plane and Feature indicator description.</summary>
  virtual void setIndicatorSymbolType(Acm::GdtSymbolType type);

  ///<summary> Return the letter identifying the datum used to indicate from the Plane and Feature indicator description.</summary>
  ///<returns>string as AcString object</returns>
  virtual AcString indicatorDatum() const;
  ///<summary> Set the letter identifying the datum used to indicate for the Plane and Feature indicator description.</summary>
  virtual void setIndicatorDatum(const AcString& value);

  ///<summary>Gets whether the all-around symbol is used for the symbol.</summary>
  virtual Acm::SurfTextAppModifierType appModifierType() const;
  ///<summary>Sets whether the all-around symbol is used for the symbol.</summary>
  virtual Acm::ErrorStatus setAppModifierType(Acm::SurfTextAppModifierType flag);

  ///<summary>Gets the position of the connection point in the geometrical specification to the leader line</summary>
  virtual Acm::FCFAttachmentPoint referenceLinePos() const;
  ///<summary>Sets the position of the connection point in the geometrical specification to the leader line.</summary>
  virtual Acm::ErrorStatus setreferenceLinePos(Acm::FCFAttachmentPoint flag);

  ///<summary>Returns the scale factor for main symbol which is aplied on all sub-symbols (excluding leader).</summary>
  virtual double symbolScale() const;

private: 
    AcmCFCFImp* mpImp{ nullptr };

};


///<summary>The Feature Control Frame class.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmFCF : public AcmSymbol
{
public:
  ACRX_DECLARE_MEMBERS(AcmFCF);

  AcmFCF();
  ///<summary>Destructures the feature control frame class.</summary>
  virtual ~AcmFCF();
  ///<summary>Gets where the leader is connected.</summary>
  Adesk::UInt8 leaderStatus() const;
  ///<summary>Gets the value of the feature control frame symbol.</summary>
  LPCTSTR value(Acm::Variable var) const;
  ///<summary>Sets the value of the feature control frame symbol.</summary>
  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::GdtSymbolType symbol() const;
  void setSymbol(Acm::GdtSymbolType sym);
  Acm::GdtSymbolType symbol2() const;
  void setSymbol2(Acm::GdtSymbolType sym);
  ///<returns>This function is only used for GOST standard.</returns>
  Acm::GdtSymbolType symbol3() const;
  ///<summary>Sets the GDT symbol type for the 3rd row.</summary>
  ///<returns>This function is only used for GOST standard.</returns>
  bool setSymbol3(Acm::GdtSymbolType sym);
  Acm::SurfTextAppModifierType appModifierType() const;
  

  ///<summary> Get type of the indicator from the Plane and Feature indicator description.</summary>
  ///<returns>enum type GdtIndicatorType as Indicator type</returns>
  Acm::GdtIndicatorType indicatorType() const;
  ///<summary> Set type of the indicator for the Plane and Feature indicator description.</summary>
  bool setIndicatorType(Acm::GdtIndicatorType type);

  ///<summary> Return type of the symbol from the Plane and Feature indicator description.</summary>
  ///<returns>enum type GdtSymbolType as symbol type</returns>
  Acm::GdtSymbolType indicatorSymbolType() const;
  ///<summary> Set type of the symbol for the Plane and Feature indicator description.</summary>
  bool setIndicatorSymbolType(Acm::GdtSymbolType type);

  ///<summary> Return the letter identifying the datum used to indicate from the Plane and Feature indicator description.</summary>
  ///<returns>string as AcString object</returns>
  AcString indicatorDatum() const;
  ///<summary> Set the letter identifying the datum used to indicate for the Plane and Feature indicator description.</summary>
  bool setIndicatorDatum(const AcString& value);

  void setAppModifierType(Acm::SurfTextAppModifierType flag);

  ///<summary>Gets the position of the connection point in the geometrical specification to the leader line</summary>
  Acm::FCFAttachmentPoint referenceLinePos() const;
  ///<summary>Sets Gets the position of the connection point in the geometrical specification to the leader line.</summary>
  Acm::ErrorStatus setreferenceLinePos(Acm::FCFAttachmentPoint flag);

  ///<summary>Defines the origin of ECS to be a start point of the sub-symbol, which is accomplished by overriding 
  ///these member functions.</summary>
  virtual void setOrigin (const AcGePoint3d &origin);
  ///<summary>Gets the origin of its sub-symbol. The origin is the same as that set by using AcmFCF::setOrigin.</summary>
  virtual AcGePoint3d getOrigin() const;

  ///<summary>Uses this overloaded member function to set up a symbol properly.</summary>
  ///<param name="pDb">Pointer to database. Default is NULL, and host databse will be used.</param>
  ///<returns>If successful then Acm::eOk is returned. If the symbol standard is not valid, then Acm::eNotSupported
  ///is returned.</returns>
  virtual Acm::ErrorStatus setSymbolDefaults(AcDbDatabase* pDb = NULL);

  ///<summary>Creates a new leader using supplied points.</summary>
  virtual Acm::ErrorStatus addLeader(const AcGePoint3dArray &ptrArray);
  ///<summary>Creates a new leader together with surface indication leader using supplied points.</summary>
  virtual Acm::ErrorStatus addLeaderWithSurfIndLeader(const AcGePoint3dArray& ptrArray);
  ///<summary>Sends a notification if the tip point of the leader has changed.</summary>
  virtual void leaderTipPointChanged(const AcGeVector3d& offset,
                                     const AcmCLeader* leader);
  ///<summary>Sends a notification if the landing of the leader has changed.</summary>
  virtual void leaderLandingChanged(const AcGeVector3d& offset,
                                    const AcmCLeader* leader);

  virtual const AcmCFCF* subSymbol() const;
  virtual AcmCFCF* subSymbol();

  virtual AcmCFCF* newSubFCF() const;

  ///<summary>This function is called during the updating of symbols that takes place when the standard is changed.</summary>
  virtual void regen();
  ///<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);

  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;

  bool setSurfExtLinesOffset(double offset);
  bool setSurfExtLinesOvershot(double overshot);
  double getSurfExtLinesOffset()const;
  double getSurfExtLinesOvershot()const;
  Adesk::Boolean returnTransformation(AcGeMatrix3d& transform, AcGePoint3d* attachPoint = nullptr, bool* isOnMText = nullptr) const;


  virtual Acm::ErrorStatus addStdCompliantLeader (const void* pGeomRef, const AcDbObjectId &viewId, const AcGePoint3d& arrowheadLocation, const AcGePoint3d& endPt);

  virtual Acm::ErrorStatus addAutoRoutingLeader(const void* pGeomRef, const AcDbObjectId &viewId, const AcGePoint3d& arrowheadLocation, AcGePoint3dArray& pointsArray);

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

  virtual INT_PTR numOfGsMarkers() const;

  ///<summary>Creates a new surface indication leader using supplied points.</summary>
  ///<param name="ptrArray">The point array specifying the start point and end point of surface indication leader.
  /// The 1st and 2nd elements in the array are the start and end points of surface indication leader correspondingly. 
  /// the other elements in the array are used to create primary leader.</param>
  ///<returns>If successful then Acm::eOk is returned. If it's not supported by current standard, then Acm::eNotSupported
  ///is returned.</returns>
  Acm::ErrorStatus addSurfIndLeader(const AcGePoint3dArray& ptrArray);
  ///<summary>Removes surface indication leader.</summary>
  Acm::ErrorStatus removeSurfIndLeader();

  ///<summary>Gets surface indication leader.</summary>
  ///<returns>Returns NULL if there is no surface indication leader.</returns>
  const AcmCLeader* getSurfIndLeader() const override;
  AcmCLeader* getSurfIndLeader() override;

  const std::vector<AcGeLineSeg3d> getBoundingLines() const;

  virtual void buildKeywordsAndPrompt(std::vector<std::pair<AcString, AcString>>& output, int idxFrame) const;
  ///<summary>...</summary>
  virtual Acm::ErrorStatus getVarFromKeyword(const AcString& keyword, Adesk::UInt32& var) const;
  virtual AcString getMessage(const Adesk::UInt32& var) const;

protected:
  virtual Adesk::Boolean    subWorldDraw(AcGiWorldDraw* mode);
  ///<summary>Lists all leaders including their vertices, standard name and original name, server name and version.</summary>
  virtual void subList() const;
  virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d& xform);
  ///<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;
  ///<summary>Queries all leaders for their grip points.</summary>
  virtual Acad::ErrorStatus subGetGripPoints(AcGePoint3dArray& gripPoints,
                                          AcDbIntArray& osnapModes,
                                          AcDbIntArray&  geomIds) 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 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  osnapMode,
                                           INT_PTR gsSelectionMark,
                                           const AcGePoint3d& pickPoint,
                                           const AcGePoint3d& lastPoint,
                                           const AcGeMatrix3d& viewXfrm,
                                           AcGePoint3dArray& snapPoints,
                                           AcDbIntArray& geomIds) const;

  virtual Acad::ErrorStatus subMoveGripPointsAt(const AcDbVoidPtrArray& gripAppData, 
                                      const AcGeVector3d& offset, 
                                      const int bitflags);

  ///<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 moveGripPointsAt member function.</summary>
  virtual Acad::ErrorStatus subMoveStretchPointsAt(const AcDbIntArray& indices,
                                                const AcGeVector3d& offset);
  virtual Acad::ErrorStatus  subGetClassID(CLSID* pClsid) const;
  void setupSecondLeader(); 

  AcGeMatrix3d getTrans4SubSymbol(bool bMTextAttached = false) const;

private:
  AcmCFCF* mpSubSymbol; 
    
};                      
DBREF_DECLARE(AcmFCF)