//////////////////////////////////////////////////////////////////////////////
//
//  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 __WELDSYM_H
#define __WELDSYM_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 AcmCWeld;
class AcmCSubWelding;
class AcmCSubWeldingList;
class AcmCWeldServiceImp;
class AcmWeldingStd;
class AcmCWeldServiceImp;
class AcmWeldingStdImp;
class AcmCSubSymbol;
class AcmCSubWeldingImp;
class AcmCWeldImp;
class AcmStringValue;

class ACMSYMBB_CRX_DLLSHARE AcmCWeld
{
public:
    AcmCWeld(AcmCSubWeldingImp* owner);
    virtual ~AcmCWeld();
    virtual Acm::SubSymbolType type() const;
    ///<summary>Returns weld type, which enables WeldingStd's getSubEnts to select the right service to handle the data.</summary>
    virtual void setType(Acm::SubSymbolType type);
    virtual Acm::SubSymbolType contourType() const;
    virtual void setContourType(Acm::SubSymbolType type);
    ///<summary>Retrieves the type of Size symbol assigned to this sub symbol. Return values include Acm::kNoneSymbol,
    ///Acm::kIntermittentWeld, and Acm::kZigzagWeld.</summary>
    virtual Acm::SubSymbolType sizeType() const;
    ///<summary>Sets the type of Size symbol assigned to this sub symbol. Parameter values include Acm::kNoneSymbol,
    ///Acm::kIntermittentWeld, and Acm::kZigzagWeld.</summary>
    virtual void setSizeType(Acm::SubSymbolType type);
    ///<summary>Retrieve the type of secondary symbol assigned to this sub symbol. Return values include Acm::kNoneSymbol,
    ///kCutEnforceWeld, kSmoothWeld, kOpenContourWeld.</summary>
    virtual Acm::SubSymbolType secSymbolType() const;
    ///<summary>Sets the type of secondary symbol assigned to this sub symbol. Parameter values include Acm::kNoneSymbol,
    ///kCutEnforceWeld, kSmoothWeld, kOpenContourWeld.</summary>
    virtual void setSecSymbolType(Acm::SubSymbolType type);
    virtual Adesk::Boolean brazing() const;

    virtual void setBrazing(Adesk::Boolean brazing);
    virtual Adesk::Boolean asSecondary() const;
    virtual Acm::WeldLocation location() const;
    virtual Acm::WeldAssociation associationType() const;
    virtual Acm::WeldSideAssociation sideAssociationType() const;
    virtual double staggerAuxDist() const;

    virtual void setStaggerAuxDist(double value);
    ///<summary>Returns the status of the weld's variable.</summary>
    virtual Adesk::Boolean isEmpty(Acm::Variable var) const;
    ///<summary>Auxiliary member functions that help to initialize dialog data surrounding the edit box for certain
    ///variables.</summary>
    virtual Acm::ErrorStatus getPrefixSuffix(Acm::Variable var,
        CString& prefix,
        CString& suffix) const;
    ///<summary>Auxiliary member functions that help to initialize dialog data surrounding the edit box for certain 
    ///variables.</summary>
    virtual Acm::ErrorStatus setPrefixSuffix(Acm::Variable var,
        LPCTSTR prefix,
        LPCTSTR suffix);

    ///<summary>Returns the pointer to the parent sub welding object. It shouldn't be deleted.</summary>
    virtual AcmCSubWelding* subWelding() const;

    ///<summary>Gets the variable value for weld.</summary>
    ///<param name="var">Var can have following values: Acm::WeldNotes, Acm::WeldSize, Acm::WeldThickness, 
    ///Acm::WeldLength, Acm::WeldNumber, Acm::WeldSpacing, Acm::WeldAngle, Acm::WeldDepth, Acm::WeldPitch, 
    ///Acm::WeldGap, Acm::WeldClearance, Acm::WeldBrazing, Acm::WeldFinishing, Acm::WeldContour.value :</param>
    virtual Acm::ErrorStatus getValue(Acm::Variable var, CString& value) const;

    ///<summary>Sets the variable value for weld.</summary>
    ///<param name="var">Var can have following values: Acm::WeldNotes, Acm::WeldSize, Acm::WeldThickness,
    ///Acm::WeldLength, Acm::WeldNumber, Acm::WeldSpacing, Acm::WeldAngle, Acm::WeldDepth, Acm::WeldPitch, 
    ///Acm::WeldGap, Acm::WeldClearance, Acm::WeldBrazing, Acm::WeldFinishing, Acm::WeldContour.value :</param>
    virtual Acm::ErrorStatus setValue(Acm::Variable var, LPCTSTR value);

    ///<summary>Gets the variable value dialog status for the weld.</summary>
    ///<param name="var">Var can have following values: Acm::WeldNotes, Acm::WeldSize, Acm::WeldThickness, 
    ///Acm::WeldLength, Acm::WeldNumber, Acm::WeldSpacing, Acm::WeldAngle, Acm::WeldDepth, Acm::WeldPitch, 
    ///Acm::WeldGap, Acm::WeldClearance, Acm::WeldBrazing, Acm::WeldFinishing, Acm::WeldContour.</param>
    ///<returns>Possible return values are: kVisible (editable, valid for the current context), kHidden 
    ///(cannot be used, not valid in the current context), kDisabled (valid, but cannot be changed in the 
    ///current context).</returns>
    virtual Acm::Visibility  variableStatus(Acm::Variable var) const;

    ///<summary>Sets the variable value dialog status for the weld.</summary>
    ///<param name="var">Var can have following values: Acm::WeldNotes, Acm::WeldSize, Acm::WeldThickness, 
    ///Acm::WeldLength, Acm::WeldNumber, Acm::WeldSpacing, Acm::WeldAngle, Acm::WeldDepth, Acm::WeldPitch, 
    ///Acm::WeldGap, Acm::WeldClearance, Acm::WeldBrazing, Acm::WeldFinishing, Acm::WeldContour.</param>
    ///<param name="status">Possible values are: kVisible (editable, valid for the current context), kHidden
    ///(cannot be used, not valid in the current context), kDisabled (valid, but cannot be changed in the current context).
    ///</param>
    virtual Acm::ErrorStatus setVariableStatus(Acm::Variable var, Acm::Visibility status);

    ///<summary>Gets the complete dialog info for the weld.</summary>
    ///<param name="var">Var can have following values: Acm::WeldNotes, Acm::WeldSize, Acm::WeldThickness, 
    ///Acm::WeldLength, Acm::WeldNumber, Acm::WeldSpacing, Acm::WeldAngle, Acm::WeldDepth, Acm::WeldPitch, 
    ///Acm::WeldGap, Acm::WeldClearance, Acm::WeldBrazing, Acm::WeldFinishing, Acm::WeldContour.</param>
    ///<param name="v">As the result it returns the object CvarDlgInfo, which holds the labels, tooltips,
    ///control index and so on.</param>
    virtual Acm::ErrorStatus getVarDlgInfo(Acm::Variable var, CVarDlgInfo& v) const;

    ///<summary>Sets the complete dialog info for the weld.</summary>
    ///<param name="var">Var can have following values: Acm::WeldNotes, Acm::WeldSize, Acm::WeldThickness,
    ///Acm::WeldLength, Acm::WeldNumber, Acm::WeldSpacing, Acm::WeldAngle, Acm::WeldDepth, Acm::WeldPitch,
    ///Acm::WeldGap, Acm::WeldClearance, Acm::WeldBrazing, Acm::WeldFinishing, Acm::WeldContour.</param>
    ///<param name="v">As the result it returns the object CvarDlgInfo, which holds the labels, tooltips, 
    ///control index and so on.</param>
    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;
    virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* filer);
    virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* filer) const;
    virtual Adesk::Boolean ISOSymbol() const;
    virtual void setISOSymbol(Adesk::Boolean newVal);

    ///<summary>Determines whether the whole sub symbol is available, or a subset. If Adesk::kTrue is returned,
    ///the full subsymbol should be available.</summary>
    virtual Adesk::Boolean isFull() const;
    ///<summary>Controls the level of availability for the subsymbol. If bIsFull is set to Adesk::kFalse, 
    ///a lesser version of the subsymbol will be available.</summary>
    virtual void setFull(Adesk::Boolean bIsFull);
    ///<summary> Set welding Distance type
    virtual void setDistanceType(Acm::WeldingDistanceType type);
    ///<summary> return current weld distance type
    virtual Acm::WeldingDistanceType distanceType() const;

    Acm::ErrorStatus initPropertyMap();
    bool isVariableVisible(const Acm::Variable varType, const AcmValue* var)const;
    LPCTSTR getVariableValue(const AcmValue* var)const;
    AcString loadString(unsigned int nId) const;

    void buildKeywordsAndPrompt(std::vector<std::pair<AcString,
        AcString>>&output,
        bool applyVisibility = true) const;
    virtual Acm::ErrorStatus setPrompt(Acm::Variable var, Adesk::UInt64 id);
    virtual Acm::ErrorStatus getVarFromKeyword(const AcString& keyword, Adesk::UInt32& var) const;
    virtual AcString message(Acm::Variable var) const;
    virtual Acm::ErrorStatus setMessage(Acm::Variable var, Adesk::UInt64 id);
    virtual Acm::ErrorStatus keyword(Acm::Variable var, AcString& keyword) const;
    virtual Acm::ErrorStatus setKeyword(Acm::Variable var, const AcString& keyword);
    virtual LPCTSTR propertyValue(Acm::Variable var) const;
    virtual Acm::ErrorStatus promptID(Acm::Variable var, Adesk::UInt64& id) const;
    virtual AcmValue* getImpValue(Adesk::UInt8 dlgIdx) const;
    AcmStringValue& backing() const;
    bool operator==(const AcmCWeld&) const;
    virtual AcmCWeld& operator = (const AcmCWeld&);

private:
    AcmCWeldImp* mpImp;
};

///<summary>Inherited from AcmCSubSymbol. The basic interface is implemented as described in AcmCSubSymbol.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmCSubWelding : public AcmCSubSymbol
{
public:
    AcmCSubWelding(AcmWelding* pSymbol);
    virtual ~AcmCSubWelding();

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

    virtual Adesk::Boolean reverseSide();
    ///<summary>Creates the new weld object.</summary>
    virtual AcmCWeld* newWeld(const AcmWeldingStd* pWeldStd = nullptr) const;
    ///<summary>Returns the orientation of the weld symbol.</summary>
    virtual Acm::Orientation orientation() const;
    virtual Acm::AlignmentType textAlign() const;
    virtual Acm::SubSymbolType areaDescType() const;

    virtual void setAreaDescType(Acm::SubSymbolType type);
    virtual Adesk::Boolean fieldWeld() const;

    virtual void setFieldWeld(Adesk::Boolean field);
    virtual Acm::IdentLineType identificationLine() const;

    virtual void setIdentificationLine(Acm::IdentLineType type);
    virtual Adesk::Boolean closedTail() const;
    virtual void setClosedTail(Adesk::Boolean status);
    virtual Acm::WeldAssociation associationType() const;
    virtual void setAssociationType(Acm::WeldAssociation type);
    virtual Acm::WeldSideAssociation sideAssociationType() const;
    virtual void setSideAssociationType(Acm::WeldSideAssociation type);
    ///<summary>Deals with welds on the arrow or non-arrow side.</summary>
    virtual AcmCWeld* weldOnArrowSide(Adesk::Boolean primary = Adesk::kTrue) const;
    ///<summary>Deals with welds on the arrow or non-arrow side</summary>
    ///<param name="isMain">If isMain is kFalse, it works with the secondary fillet.</param>
    virtual Adesk::Boolean setWeldOnArrowSide(AcmCWeld* pNewWeld,
        Adesk::Boolean primary = Adesk::kTrue);
    ///<summary>Deals with welds on the arrow or non-arrow side.</summary>
    virtual AcmCWeld* weldOnOtherSide(Adesk::Boolean primary = Adesk::kTrue) const;
    ///<summary>Deals with welds on the arrow or non-arrow side</summary>
    ///<param name="isMain">If isMain is kFalse, it works with the secondary fillet.</param>
    virtual Adesk::Boolean setWeldOnOtherSide(AcmCWeld* pNewWeld,
        Adesk::Boolean primary = Adesk::kTrue);
    virtual void setNewSymbolRev(Adesk::Boolean newRev = Adesk::kTrue);
    virtual Adesk::Boolean newSymbolRev() const;
    ///<summary>Allows access to the Weld symbol?s leader points. The input parameter index specifies which 
    ///branch will be iterated over, and the resulting points are copied into gripPoints.</summary>
    virtual Acm::ErrorStatus getLeaderPoints(Adesk::UInt16 index, AcGePoint3dArray& gripPoints) const;

    enum AmcSubweldingValues
    {
        kIdentLine = 0,
        kNotes,
        kWeldIndex,
        kWeldIndexTotal,
        kWeldControlCategory,
        kWeldClosedTail,
        kLastElement  //must be last!
    };

    virtual Acm::ErrorStatus getKeywordAndPrompt(const AmcSubweldingValues& var, AcString& keyword, AcString& prompt) const;
    virtual Acm::ErrorStatus getVarForKeyword(const AcString& keyword,
        Adesk::UInt32& var,
        bool& bIsSubWeld,
        bool isArrowSide,
        bool isMain) const;
    virtual void buildKeywordsAndPrompt(std::vector<std::pair<AcString, AcString>>& output,
        bool isArrowSide,
        bool isMain,
        bool applyVisibility = true) const;
    virtual void setPrompt(const Adesk::UInt32& var, bool bIsSubWeld, Adesk::UInt64);
    virtual AcString getMessage(const Adesk::UInt32& var,
        bool isSubweld,
        bool isArrowSide,
        bool isMain) const;

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

    bool operator== (const AcmCSubWelding&) const;
    virtual AcmCSubWelding& operator = (const AcmCSubWelding&);

    void setVerSchema(Adesk::UInt16 ver);

private:
    AcmCSubWeldingImp* mpImp;
};

///<summary>This class has a friend class (AcmCWeldBaseService) described below, and a large number of
///successors. For a complete list see weldserv.h.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmCWeldService
{
  friend class AcmSymbbInternals;
public:
  ///<summary>Destructures the welding symbol standard class. Base initialization called from the standard.</summary>
  virtual ~AcmCWeldService();
  ///<summary>Protected in weldsym.h. It can be used in derived classes only.</summary>
  LPCTSTR            serviceName() const;
  ///<summary>Returns the type of weld service.</summary>
  Acm::SubSymbolType serviceType() const;
  ///<summary>Returns the group of this service.</summary>
  Acm::WeldGroup     group() const;
  ///<summary>Gets the allowed placement of a weld symbol, which specifies for which side the service could be used.</summary>
  Acm::WeldLocation  allowedLocation() const;
  ///<summary>Define whether the weld type specified by the service can be used in the weld symbol on one side only
  /// The allowedLocation method specify where the symbol can be placed but we do not allow to place another weld symbol
  /// on opposite side. Default state is false so we allow welding symbol on the both side.</summary>
  Adesk::Boolean oneSideLocation() const;
  ///<summary>Returns allowed stagger types bit flag.</summary>
  void allowedStaggerType(Adesk::UInt32& value) const;
  ///<summary>Enables the insertion of a spacer - its symbol breaks the reference line.</summary>
  Adesk::UInt32     enableSpacer() const;
  ///<summary>Returns the alignment type of the symbol created by this service.</summary>
  Acm::AlignmentType alignment() const;
  ///<summary>Returns the distance to be used when aligning the symbol to center.</summary>
  virtual double alignSize() const;
  ///<summary>Gets whether the service is hidden in the standard preference setting dialog.</summary>
  Adesk::Boolean hidden() const;
  ///<summary>Sets that the service is hidden in the standard preference setting dialog.</summary>
  void setHidden(Adesk::Boolean hide);
  double leftTxtStartPosition(Acm::WeldLocation loc) const;
  void setLeftTxtStartPosition(Acm::WeldLocation loc, double pos);
  double rightTxtStartPosition(Acm::WeldLocation loc) const;
  void setRightTxtStartPosition(Acm::WeldLocation loc, double pos);
  ///<summary>Loads the bitmap of the weld service.</summary>
  ///<param name="flip">Flipped is true for arrow side page, false otherwise.</param>
  virtual HBITMAP loadBitmap(Adesk::Boolean flip = Adesk::kFalse) const;
  ///<summary>Loads the bitmap of the weld service according to location.
  ///For kForArrowSide we use the flipped representation otherwise normal representation.</summary>
  ///<param name="filter">Acm::WeldLocationFilter enum which define location of sub weld</param>
  virtual HBITMAP loadBitmap4Loc(Acm::WeldLocationFilter filter = Acm::kForBothSides) const;
  ///<summary>This function has the same responsibility as the one in the symbol standard. It is used for each
  ///particular weld symbol to edit it properly. It is used in the current UI, but can also be used in any 
  ///alternative one.</summary>
  virtual Acm::ErrorStatus setSuggested(AcmCWeld* pWeld) const;
  ///<summary>This function has the same responsibility as the one in the symbol standard. It is used for 
  ///each particular weld symbol to edit it properly. It is used in the current UI, but can also be used in
  ///any alternative one.</summary>
  virtual Acm::ErrorStatus checkVisibility(AcmCWeld* pWeld) const;
  ///<summary>This function has the same responsibility as the one in the symbol standard. It is used for each 
  ///particular weld symbol to edit it properly. It is used in the current UI, but can also be used in any 
  ///alternative one.</summary>
  virtual Acm::ErrorStatus initFields(AcmCWeld* pWeld) const;
  ///<summary>Used for spacer-enabled services to get the extents for the break of the reference line.</summary>
  virtual Acm::ErrorStatus getBreakExtents(AcDbExtents& ext,
                                  const AcmCWeld* pWeld) const;
  ///<summary>Returns the matrix, which is used to attach contour symbols.</summary>
  virtual Acm::ErrorStatus linkDef(const AcmCWeld* pWeld,
                                   AcGeMatrix3d& trans) const;
  ///<summary>Returns eOk if the service supports secondary fillets.</summary>
  virtual Acm::ErrorStatus secondaryFillet(const AcmCWeld* pWeld,
                                           AcGePoint3d& pt) const;
  ///<summary>This function has the same responsibility as the one in the symbol standard. It is used for each 
  ///particular weld symbol to edit it properly. It is used in the current UI, but can also be used in any 
  ///alternative one.</summary>
  virtual void getSubEnts(AcmCWeld* pWeld, AcmCAuxEntArray& entArray);
  ///<summary>Calculates the transformation matrix for the weld symbol.</summary>
  ///<param name="pWeld">Determines where the symbol is located - on the arrow side or on the other side of the symbol.</param>
  ///<param name="trans">The matrix is then used to transform sub-entities to their final positions.</param>
  virtual Acm::ErrorStatus getTransform(const AcmCWeld *pWeld,
                                        AcGeMatrix3d& trans) const;
  ///<summary>Returns the type of attachment points of the contour symbol.</summary>
  virtual AcDbMText::AttachmentPoint attachContourText(const AcmCWeld* pWeld) const;  

  virtual AcString serviceCLIprompt() const;
  virtual AcString serviceCLIkeyword() const;

  //////////////////////////////////////////////////////////////////////////
  //Contour geom extent interface
  ///<summary>Set geom extend of contour symbol geometry.</summary>
  virtual Acm::ErrorStatus setContourGeomExtents(const AcDbExtents& extents);
  ///<summary>Add geom extend of subentity into contour symbol geom extent.</summary>
  virtual Acm::ErrorStatus addContourGeomExtents(const AcDbExtents& extents);
  ///<summary>Return geom extend of countour symbol geometry.</summary>
  virtual Acm::ErrorStatus getContourGeomExtents(AcDbExtents& extents) const;

protected:
  AcmCWeldService();
  AcmWeldingStd* ownerWeldStd() const;
  void setServiceName(LPCTSTR srvName);
  ///<summary>Returns the internal service name, which is used in the dialog box or for other identification 
  ///purposes. Needed for derived classes.</summary>
  void setServiceNameRcId(UINT rcSrvNameId);
  void setGroup(Acm::WeldGroup grp);

  void setServiceType(Acm::SubSymbolType srvType);
  void setAllowedStaggerType(Adesk::UInt32 value);
  void setEnableSpacer(Adesk::UInt32 value);
  void setAllowedLocation(Acm::WeldLocation loc);
  void setOneSideLocation(Adesk::Boolean bOneSide);
  void setAlignment(Acm::AlignmentType aType);
  virtual void initTexts(AcmCWeld* pWeld);
  virtual Acm::ErrorStatus initPost(AcmCWeld* pWeld) const;
  virtual HINSTANCE serviceResourceHandle() const;
  UINT bitmapRcId() const;
  void setBitmapRcId(UINT bmpRcId);
  UINT bitmapFilpRcId() const;
  void setBitmapFlipRcId(UINT bmpRcId);
  virtual void getBasicSymbol(AcmCWeld* pWeld,
                              double scaledH,
                              double gap,
                              const AcCmColor & symColor,
                              AcmCAuxEntArray& entArray);
  virtual void getBasicSymbol(AcmCWeld* pWeld,
                              double scaledH,
                              double gap,
                              Adesk::UInt16 symColor,
                              AcmCAuxEntArray& entArray);

  // Internal methods to set weld service CLI prompt string (with a resource ID) and keyword
  // This is used only in CLI version -AMWELDSYM (AcmWeldingOptionCommand)
  virtual void setServiceCLIpromptRcId(UINT serviceCLIpromptUID);
  virtual void setServiceCLIkeyword(const AcString& serviceCLIkeyword);

private:
  AcmCWeldServiceImp *mpImp;
};


///<summary>This is class AcmCWeldBaseService.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmCWeldBaseService : public AcmCWeldService
{
public:

  virtual Acm::ErrorStatus initFields(AcmCWeld* pWeld) const;
  
  virtual Acm::ErrorStatus checkVisibility(AcmCWeld* pWeld) const;

  virtual Acm::ErrorStatus setSuggested(AcmCWeld* pWeld) const;

  virtual void getSubEnts(AcmCWeld* pWeld, AcmCAuxEntArray& entArray);
  virtual Acm::ErrorStatus drawBrazing(const AcmCWeld* pWeld,
                                       AcmCAuxEntArray& entArray);

  //////////////////////////////////////////////////////////////////////////
  ///<summary>Virtual methods for overriding of symbol drawing for each distance
  /// type (Acm::WeldingDistanceType enum). The default implementations are empty and 
  /// derived classes override them in case if they want to draw symbols for various
  /// distance type.</summary>
  virtual void drawIntermittentWeld(AcmCWeld* pWeld, AcDbExtents& extSymbol, AcmCAuxEntArray& entArray);
  virtual void drawTwoPointWeld(AcmCWeld* pWeld, AcDbExtents& extSymbol, AcmCAuxEntArray& entArray);
  virtual void drawContinuousWeld(AcmCWeld* pWeld, AcDbExtents& extSymbol, AcmCAuxEntArray& entArray);
  virtual void drawFromToWeld(AcmCWeld* pWeld, AcDbExtents& extSymbol, AcmCAuxEntArray& entArray);
  virtual void drawToFromWeld(AcmCWeld* pWeld, AcDbExtents& extSymbol, AcmCAuxEntArray& entArray);

  //////////////////////////////////////////////////////////////////////////
  ///<summary>Virtual methods for overriding of property varaibles to be visible for each distance
  /// type (Acm::WeldingDistanceType enum). The default implementations are empty and 
  /// derived classes override them in case if they want to have different properties for various
  /// distance type.</summary>
  virtual void initFields_Intermittent(AcmCWeld* pWeld) const;
  virtual void initTexts_Intermittent(AcmCWeld* pWeld);
  virtual void checkVisibility_Intermittent(AcmCWeld* pWeld) const;

  virtual void initFields_TwoPoint(AcmCWeld* pWeld) const;
  //////////////////////////////////////////////////////////////////////////

  virtual double spacingSize() const;

protected:
  virtual void initTexts(AcmCWeld* pWeld);
  virtual Acm::ErrorStatus initPost(AcmCWeld* pWeld) const;
  virtual void getBasicSymbol(AcmCWeld* pWeld,
                              double scaledH,
                              double gap, 
                              const AcCmColor & symColor,
                              AcmCAuxEntArray& entArray);
  virtual void getBasicSymbol(AcmCWeld* pWeld,
                              double scaledH,
                              double gap, 
                              Adesk::UInt16 symColor,
                              AcmCAuxEntArray& entArray);
  virtual void brazing(const AcGePoint3d& p1,
                       const AcGePoint3d& p2,
                       const AcGePoint3d& p3,
                       LPCTSTR value,
                       AcmCAuxEntArray& entArray,
                       double arwSize = - 1.0);
};


///<summary>This is class AcmCContourWeldService.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmCContourWeldService : public AcmCWeldService
{
public:
  AcmCContourWeldService();
  
  virtual Acm::ErrorStatus getTransform(const AcmCWeld *pWeld,
                                        AcGeMatrix3d& trans) const;
  virtual AcDbMText::AttachmentPoint attachContourText(const AcmCWeld* pWeld) const;

  //////////////////////////////////////////////////////////////////////////
  //Contour geom extent set interface overrides
  Acm::ErrorStatus setContourGeomExtents(const AcDbExtents& extents) override;
  Acm::ErrorStatus addContourGeomExtents(const AcDbExtents& extents) override;
  Acm::ErrorStatus getContourGeomExtents(AcDbExtents& extents) const override;

private:
    ///<summary>Geom extension of the geometry of contour symbols. Each derived class is responsible for setting up this member</summary>
    AcDbExtents mExtContour;
};


///<summary>This class is responsible for welding sub-symbols and implements all of its virtual member functions. 
///It contains several services to handle all types of weld symbols. The structure of the welding symbol is more
///complex than that of any other symbol.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmWeldingStd : public AcmSymbolStd
{
  friend class AcmSymbbInternals;
public:
  ACRX_DECLARE_MEMBERS(AcmWeldingStd);
  ///<summary>Destructures the welding symbol standard class.</summary>
  virtual ~AcmWeldingStd();

  const ACHAR* getBaseSymStdClassName() const override;
  ///<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();
  ///<summary>Sets the factory default values.</summary>
  virtual Adesk::Boolean setFactoryDefaults();
  virtual void setDefaultSubSymbol(AcmCSubWelding* pData) const;
  virtual void setDefaultSubWeld(AcmCWeld* pData) const;
  virtual Acm::ErrorStatus getDescription(CString& desc,
                                          CBitmap*& pBmpLoaded,
                                          CBitmap*& pBmpReg,
                                          Adesk::Boolean& enablePref) const;
  AcDbObjectId identLtypeId() const;
  Acm::ErrorStatus setIdentLtypeId(const AcDbObjectId& idType);
  Acm::ErrorStatus getIdentLtypeName(ACHAR*& pName) const;
  Acm::ErrorStatus setIdentLtypeName(const ACHAR* pName);
  double identLineGap() const;
  void setIdentLineGap(double value);
  double currentIdentLineGap() const;
  void setCurrentIdentLineGap(double value);
  double symbolGap() const;
  void setSymbolGap(double value);
  double currentSymbolGap() const;
  void setCurrentSymbolGap(double value);
  double scaledHeight() const;
  
  int distPalettePos() const;
  void setDistPalettePos(int value);
  int secondaryDistPalettePos() const;
  void setSecondaryDistPalettePos(int value);

  virtual UINT dialogPageResourceIDD() const;

  ///<summary>For internal use only.</summary>
  virtual double extraScaleFactor() const;
  ///<summary>For internal use only.</summary>
  virtual double legacyProcessGap() const;
  ///<summary>Return the scale factor in current welding standard settings. 
  ///A double value (which is larger than 0) will be returned.</summary>
  virtual double currentScaleFactor() const;
  ///<summary>Set the scale factor to current welding standard settings. 
  /// Acm::eOk is returned if it is successful. Acm::eNotSupported is returned for GOST standard.</summary>
  virtual Acm::ErrorStatus setCurrentScaleFactor(double scale);
  ///<summary>Return the process gap in current welding standard settings. 
  /// A double value (which is larger than 0) will be returned.</summary>
  virtual double currentProcessGap() const;
  ///<summary>Set the process gap to current welding standard settings. 
  ///Acm::eOk is returned if it is successful. Acm::eNotSupported is returned for GOST standard.</summary>
  virtual Acm::ErrorStatus  setCurrentProcessGap(double gap);
  Adesk::Boolean allowedClosedTail() const;
  void setAllowedClosedTail(Adesk::Boolean status);
  Adesk::Boolean   allowedISOSymbols(const AcmCSubWelding* pSubWeld = NULL) const;  
  void setAllowedISOSymbols(Adesk::Boolean flag);
  virtual Adesk::Boolean   allowedIdentLine(const AcmCSubWelding* pSubWeld = NULL) const;  
  virtual void allowedStaggerType(const AcmCSubWelding* pWelding, Adesk::UInt32& value) const;
  virtual Adesk::Boolean   allowedSpacer(const AcmCSubWelding* pWelding) const;
  ///<summary>Gets the default placement of a weld symbol</summary>
  virtual Acm::WeldLocation  defaultLocation() const;
  ///<summary>Returns the list of description objects for welds on each side of the sub-welding.</summary>
  virtual Adesk::Boolean getWelds(const AcmCSubWelding *pSubWeld,
                                  Acm::WeldLocationFilter filter,
                                  AcmCObjArray<AcmCSymbolDesc>& list,
                                  Adesk::Boolean bISOSymbol = Adesk::kFalse) const;
  ///<summary>Gets the list of allowed welds in the specified group.</summary>
  virtual Adesk::Boolean getWeldDesc(AcmCObjArray<AcmCSymbolDesc>& list,
                                     Acm::WeldGroup wGroup = Acm::kWeld,
                                     Acm::WeldLocationFilter filter = Acm::kForBothSides,
                                     Adesk::Boolean bISOSymbol = Adesk::kFalse) const;
  ///<summary>Sets the list of allowed welds in the specified group.</summary>
  virtual Adesk::Boolean setWeldDesc(const AcmCObjArray<AcmCSymbolDesc>& list, int ISOStartIndex = -1);
  AcmCWeldService* getService(Acm::SubSymbolType wType, Adesk::Boolean bISOSymbol = Adesk::kFalse) const;
  Adesk::Boolean isOfferedService(Acm::SubSymbolType wType) const;
  AcmCWeldService* serviceAt(Adesk::UInt32 at) const;
  Adesk::UInt32 numOfServices() const;
  Adesk::Boolean removeService(Acm::SubSymbolType wType);
  Adesk::Boolean removeServiceAt(Adesk::UInt32 at);
  void initToEditOriginal() const override;
  void initToEdit() const override;
  virtual Adesk::Boolean initPost(AcmCWeld* pWeld) const;
  virtual Acm::ErrorStatus setSuggested(AcmCSubWelding* pData) const;
  virtual Acm::ErrorStatus getSuggestedFinished(std::vector<AcString>& descList, 
                                                std::vector<AcString>* pKeywordList = nullptr) const;
  virtual Acm::ErrorStatus checkVisibility(AcmCSubWelding* pData) const;
  virtual Acm::ErrorStatus initFields(AcmCSubWelding* pData) const;
  virtual void getSubEnts(const AcmCSubWelding* pSubSym,
                          AcmCAuxEntArray& subents,
                          AcGePoint3d& ptRefEnd) 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 AcmWeldingStd::Variable.</summary>
  enum Variable {
    kIdentLineType = 0,
    kIdentLineGap,    
    kAllowISOSymbols,
    kSymbolSize
  };
  virtual Acm::Visibility variableStatus(AcmWeldingStd::Variable var) const;
  virtual void setVariableStatus(AcmWeldingStd::Variable var, Acm::Visibility status) const;
  ///<summary>Returns Adesk::kTrue if welding standards (such as ANSI) allow multiple welding symbols (sub-weldings) 
  ///to be connected to one leader.</summary>
  virtual Adesk::Boolean isMultipleSymbolsAllowed() const;  
  virtual void setDefaultISOSettings();
  ///<param name="bufStr">Reference to CString object to be populated with prefix string.</param>
  virtual void getWeldProcessPrefix(CString& bufStr) const;
  ///<summary>Allows the SymStandard to fill list with the list of weld standards used by this symbol standard. 
  ///The default implementation does not edit the list parameter.</summary>
  ///<param name="list">Reference to CString object to be populated with prefix string.</param>
  virtual void getDefaultStandardList(AcArray<CString>& list) const;

  ///<summary>Returns all supported insertion types of welding processes.</summary>
  virtual UINT getProcessInsertTypes() const;
  ///<summary>Returns all supported types of welding processes</summary>
  virtual UINT getProcessTypes() const;

  ///<summary>Return true if welding standards allow distance palette.</summary>
  virtual Adesk::Boolean isDistancePaletteAllowed() const;
  ///<summary>Returns the list of available distance types(Acm:WeldingDistanceType enum values)</summary>
  virtual std::vector<Adesk::UInt16> getAllowedDistanceTypes() const;
  ///<summary>Returns the resource ID of Bitmap for given distance type(Acm:WeldingDistanceType enum value)</summary>
  virtual Adesk::UInt64 getDistanceBitmap(Acm::WeldingDistanceType var) const;
  ///<summary>Returns the resource ID of message for given distance type(Acm:WeldingDistan enum value)
  ///The switch bCLVersion defines if returned message is for GUI or CLI</summary>
  virtual Adesk::UInt64 getDistancePrompt(Acm::WeldingDistanceType var, bool bCLVersion = false) const;
  ///<summary>Returns the string of CL keyword for given distance type(Acm:WeldingDistan enum value)</summary>
  virtual AcString getDistanceKeyword(Acm::WeldingDistanceType var) const;
  ///<summary>Returns the welding distance type for given CLI keyword.</summary>
  virtual Acm::WeldingDistanceType getDistance4Keyword(const AcString& keyword) const;

  ///<summary> return gdt Style object ID</summary>
  virtual AcDbObjectId gdtStyleId() const;  

  ///<summary> return true when gap row need to show with identification line</summary>
  virtual Adesk::Boolean isGapRowEnableWithIndentLine() const;

  ///<summary> return true when the operation is enabled on the welding</summary>
  virtual Adesk::Boolean allowedOperation() const;

  ///<summary> return true when the Spacer is enabled on the welding</summary>
  virtual Adesk::Boolean allowedSpacer() const;

protected:
  void setAllowedIdentLine(Adesk::Boolean flag);  
  Adesk::Boolean registerService(AcmCWeldService* pNewServ, Adesk::Boolean bISOSymbol = Adesk::kFalse);
  virtual void getSideSubEnts(AcmCWeld* pWeld,
                              AcmCWeld* pWeldS,
                              AcmCAuxEntArray& entitySet,
                              Acm::AlignmentType& align,
                              double& moveX) const;
  virtual Acad::ErrorStatus   subGetClassID(CLSID* pClsid) const;
  ///<summary>For internal use only.</summary>
  virtual double subGetProcessGap() const;

  /// return true if welding standards showing complete list in weld symbol palette
  virtual Adesk::Boolean ShownBackingWeldInSymbPalette() const;

  /// create gdt style
  virtual Acad::ErrorStatus createDefaultStyle(LPCTSTR styleName, LPCTSTR fontName);

  ///<summary>Constructs the welding symbol standard class. The constructor is protected. This class cannot be 
  ///instantiated.</summary>
  AcmWeldingStd();

private:
  AcmWeldingStdImp *mpImp;
};
DBREF_DECLARE(AcmWeldingStd)


///<summary>This existing class is the class for welding object.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmWelding : public AcmSymbol
{
public:
  ACRX_DECLARE_MEMBERS(AcmWelding);
  AcmWelding();
  virtual ~AcmWelding();

  Acm::SubSymbolType type(Adesk::Boolean arwSide = Adesk::kTrue,
                          Adesk::Boolean primary = Adesk::kTrue,
                          Adesk::UInt16 subWelding = 0) const;
  
  void setType(Acm::SubSymbolType type,
               Adesk::Boolean arwSide = Adesk::kTrue,
               Adesk::Boolean primary = Adesk::kTrue,
               Adesk::UInt16 subWelding = 0);
  
  Acm::SubSymbolType contourType(Adesk::Boolean arwSide = Adesk::kTrue,
                                 Adesk::Boolean primary = Adesk::kTrue,
                                 Adesk::UInt16 subWelding = 0) const;
  
  Adesk::Boolean setContourType(Acm::SubSymbolType type,
                      Adesk::Boolean arwSide = Adesk::kTrue,
                      Adesk::Boolean primary = Adesk::kTrue,
                      Adesk::UInt16 subWelding = 0);

  Acm::SubSymbolType sizeType(Adesk::Boolean arwSide = Adesk::kTrue,
                              Adesk::Boolean primary = Adesk::kTrue,
                              Adesk::UInt16 subWelding = 0) const;

  void setSizeType(Acm::SubSymbolType type,
                   Adesk::Boolean arwSide = Adesk::kTrue,
                   Adesk::Boolean primary = Adesk::kTrue,
                   Adesk::UInt16 subWelding = 0);

  Acm::SubSymbolType secSymbolType(Adesk::Boolean arwSide = Adesk::kTrue,
                                   Adesk::Boolean primary = Adesk::kTrue,
                                   Adesk::UInt16 subWelding = 0) const;

  void setSecSymbolType(Acm::SubSymbolType type,
                        Adesk::Boolean arwSide = Adesk::kTrue,
                        Adesk::Boolean primary = Adesk::kTrue,
                        Adesk::UInt16 subWelding = 0);

  Adesk::Boolean brazing(Adesk::Boolean arwSide = Adesk::kTrue,
                         Adesk::Boolean primary = Adesk::kTrue,
                         Adesk::UInt16 subWelding = 0) const;

  void setBrazing(Adesk::Boolean brazing,
                  Adesk::Boolean arwSide = Adesk::kTrue,
                  Adesk::Boolean primary = Adesk::kTrue,
                  Adesk::UInt16 subWelding = 0);

  LPCTSTR value(Acm::Variable var,
                Adesk::Boolean arwSide = Adesk::kTrue,
                Adesk::Boolean primary = Adesk::kTrue,
                Adesk::UInt16 subWelding = 0) const;

  Acm::ErrorStatus getValue(Acm::Variable var,
                            CString& value,
                            Adesk::Boolean arwSide = Adesk::kTrue,
                            Adesk::Boolean primary = Adesk::kTrue,
                            Adesk::UInt16 subWelding = 0) const;
  Acm::ErrorStatus setValue(Acm::Variable var,
                            LPCTSTR value,
                            Adesk::Boolean arwSide = Adesk::kTrue,
                            Adesk::Boolean primary = Adesk::kTrue,
                            Adesk::UInt16 subWelding = 0);

  Acm::Visibility variableStatus(Acm::Variable var,
                                 Adesk::Boolean arwSide = Adesk::kTrue,
                                 Adesk::Boolean primary = Adesk::kTrue,
                                 Adesk::UInt16 subWelding = 0) const;

  Acm::ErrorStatus setVariableStatus(Acm::Variable var,
                                     Acm::Visibility status,
                                     Adesk::Boolean arwSide = Adesk::kTrue,
                                     Adesk::Boolean primary = Adesk::kTrue,
                                     Adesk::UInt16 subWelding = 0);

  Acm::ErrorStatus getVarDlgInfo(Acm::Variable var,
                                 CVarDlgInfo& v,
                                 Adesk::Boolean arwSide = Adesk::kTrue,
                                 Adesk::Boolean primary = Adesk::kTrue,
                                 Adesk::UInt16 subWelding = 0) const;

  Acm::ErrorStatus setVarDlgInfo(Acm::Variable var,
                                 const CVarDlgInfo& v,
                                 Adesk::Boolean arwSide = Adesk::kTrue,
                                 Adesk::Boolean primary = Adesk::kTrue,
                                 Adesk::UInt16 subWelding = 0);

  Acm::SubSymbolType areaDescType(Adesk::UInt16 subWelding = 0) const;
  void setAreaDescType(Acm::SubSymbolType type, Adesk::UInt16 subWelding = 0);

  Adesk::Boolean fieldWeld(Adesk::UInt16 subWelding = 0) const;
  void setFieldWeld(Adesk::Boolean field, Adesk::UInt16 subWelding = 0);

  Acm::IdentLineType identificationLine(Adesk::UInt16 subWelding = 0) const;
  void setIdentificationLine(Acm::IdentLineType type, Adesk::UInt16 subWelding = 0);
  
  Adesk::Boolean closedTail(Adesk::UInt16 subWelding = 0) const;
  ///<summary>This function will return error codes to check if user can set closed tail for welding symbol. 
  ///It is failed if closed tail is not support by current symbol standard or welding notes is empty.</summary>
  Acm::ErrorStatus setClosedTail(Adesk::Boolean status, Adesk::UInt16 subWelding = 0);
  
  Acm::WeldAssociation associationType(Adesk::UInt16 subWelding = 0) const;
  void setAssociationType(Acm::WeldAssociation type, Adesk::UInt16 subWelding = 0);

  Acm::WeldSideAssociation sideAssociationType(Adesk::UInt16 subWelding = 0) const;
  void setSideAssociationType(Acm::WeldSideAssociation type, Adesk::UInt16 subWelding = 0);

  virtual Acm::ErrorStatus setSymbolDefaults(AcDbDatabase* pDb = NULL);
  virtual AcmCSubWelding* newSubWelding() const;
  
  Acm::ErrorStatus setOrientation(Acm::Orientation orientation);
  Acm::Orientation orientation() const;

  void setTextAlign(const Acm::AlignmentType align);
  Acm::AlignmentType textAlign() const;

  Acm::ErrorStatus addSubWelding(AcmCSubWelding* pSubWelding);
  Adesk::Boolean insertSubWeldingBefore(Adesk::UInt16 index,
                                        AcmCSubWelding* pSubWelding);
  Adesk::Boolean insertSubWeldingBefore(Adesk::UInt16 index);

  //obsolete functions. Do not use - they will be removed!
  AcmCSubWelding* getPrevSubWelding(AcmCSubWelding* pThisSubWelding) const;
  AcmCSubWelding* getNextSubWelding(AcmCSubWelding* pThisSubWelding) const;
  Adesk::UInt16   findSubWelding(AcmCSubWelding* pSubWelding) const;

  Adesk::Boolean  removeSubWelding(Adesk::UInt16 index);
  void            removeAllSubWeldings();
  Adesk::UInt16   numOfSubWeldings() const;
  AcmCSubWelding* subWelding(Adesk::UInt16 index) const;
  void resetOrigins();
  virtual void leaderTipPointChanged(const AcGeVector3d& offset,
                                     const AcmCLeader* leader) override;

  virtual void leaderSecondTipPointChanged(const AcGeVector3d& offset,
                                           const AcmCLeader* leader) override;

  void weldHighlight(Adesk::UInt16 num) const;
  void weldUnhighlight(Adesk::UInt16 num) const;

  void buildKeywordsAndPrompt(std::vector<std::pair<AcString, AcString>>&output,
      Adesk::UInt16 operation = 0,
      bool arrowSide = true,
      bool mainProcess = true) const;
  Acm::ErrorStatus getVarForKeyword(const AcString& keyword,
      Adesk::UInt32& var, 
      bool& bIsSubWeld,
      Adesk::UInt16 operation = 0,
      bool arrowSide = true,
      bool mainProcess = true) const;
  AcString getMessage(const Adesk::UInt32& var,
      bool isSubWeld,
      Adesk::UInt16 operation,
      bool arrowSide,
      bool mainProcess) const;


  using AcmSymbol::transformBy;
  ///<summary>Transforms all leaders. Default implementation doesn't cover any smart behavior.</summary>
  virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform, double symbolScale);
  ///<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* pFiler);
  virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler) const;
  virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* pFiler);
  virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* pFiler) const;
  virtual Acm::ErrorStatus removeLeader(Adesk::UInt16 index);
  
  virtual void setNewSymbolRev(Adesk::Boolean newRev = Adesk::kTrue);
  virtual Adesk::Boolean newSymbolRev() const;

  ///<summary>this method inserts process to the tail note.</summary>
  ///<param name="withPrefix">Specifies whether inserts process prefixed by the standard's standard number (or full designation).</param>
  virtual Acm::ErrorStatus insertProcess(const ACHAR* process, Adesk::Boolean withPrefix = Adesk::kFalse, Adesk::UInt16 subWelding = 0);

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

  bool isSILJigging() const;
  void setIsSILJigging(bool silJigging);

  bool isAddSILeaderEnabled() const;

protected:
  virtual Adesk::Boolean    subWorldDraw(AcGiWorldDraw* pMode);
  Adesk::Boolean resetOrigins(const AcGePoint3d& tip,const AcGePoint3d& prev);
  Adesk::Boolean getLeaderLastTwoPoints(AcGePoint3d& tip,AcGePoint3d& prev) const;
  virtual Acad::ErrorStatus subGetSubentPathsAtGsMarker(AcDb::SubentType     type,
                                                     INT_PTR              gsMark,
                                                     const AcGePoint3d&   pickPoint,
                                                     const AcGeMatrix3d&  viewXform, 
                                                     int&                 numPaths,
                                                     AcDbFullSubentPath*& subentPaths, 
                                                     int                  numInserts = 0,
                                                     AcDbObjectId*        entAndInsertStack = NULL) const;
  virtual Acad::ErrorStatus subGetGsMarkersAtSubentPath(const AcDbFullSubentPath& subPath, 
                                                     AcArray<INT_PTR>& gsMarkers) const;
  virtual AcDbEntity*  subSubentPtr(const AcDbFullSubentPath& id) 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>Sums geometry extents for a leader.</summary>
  virtual Acad::ErrorStatus subGetGeomExtents(AcDbExtents& extents) const;
  virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d& xform);
  ///<summary>Lists all leaders including their vertices, standard name and original name, server name and version.</summary>
  virtual void subList() const;
  ///<summary>Queries all leaders for their grip points.</summary>
  virtual Acad::ErrorStatus subGetGripPoints(AcGePoint3dArray& gripPnts,
                                          AcDbIntArray& osnapMasks,
                                          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 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;

private:
    AcmCSubWeldingList* mpSubWeldings{ nullptr };

  //not persisted
  bool mIsSILJigging{ false };

};
DBREF_DECLARE(AcmWelding)

#endif // __WELDSYM_H
