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

// DESCRIPTION: This file contains base definitions used throughout
//              the MCAD API.
//
#ifndef AMIBASE_H
#define AMIBASE_H

#include <tchar.h>
#ifndef _ADESK_MAC_
#include <basetsd.h>
#endif
#include "rxobject.h"
#include "dbid.h"
#include "dbmain.h"
#include "gevec3d.h"
#include "gepnt3d.h"

#include "miStatus.h"
#include "miarray.h"
#include "AdAChar.h"

class AcApDocument;

#define NULL_FUNC_PTR       (AmiNullFuncPtr)0
#define UNSET_FUNC_ID       -1
#define UNSET_APP_ID        -1
#define NUM_INIT_API_FUNCS  400 // Maximum number of registered functions.
#define NUM_INIT_APPS       5

class AcDbDwgFiler;
class AcDbDatabase;
class AcDbFullSubentPath;
class AcGePoint3d;
class AcDbSubentId;
class AcDbObjectId;
class AcMeDoc;
class AcDbXrefGraph;

namespace Ami
{
    ///<summary>Enumeration of valid key types.</summary>
    enum KeyType
    {
        objectKey,
        geomKey,
        pointKey,
        curveKey,
        lineKey,
        arcKey,
        ellipseKey,
        splineCrvKey,
        polylineKey,
        auglineKey,
        surfKey,
        planeKey,
        coneKey,
        cylinderKey,
        sphereKey,
        torusKey,
        splineSrfKey,
        constrKey,
        compConstrKey,
        sketchConstrKey,
        paramKey,
        sketchKey,
        featKey,
        bodyKey,
        solidKey,
        partKey,
        compKey,
        compDefKey,
        sceneKey,
        vectorKey,
        sketchPlaneKey,
        oldSize,            // for binary compat., keep placeholder
        quiltKey,
        compViewKey,
        compViewDefKey,
        folderKey,
        folderDefKey,
        annotationViewDefKey,
        hideKey,
        cpxHideKey,
        size
    };


    enum DesignEnvironmentType
    {
       ///<summary>Database only contains components, no parts.</summary>
       kPartAssembly,  // Database only contains components, no parts.
       ///<summary>Database only contains a single part, no components.</summary>
       kSinglePart,    // Database only contains a single part, no components.
       ///<summary>File was created on a newer Desktop. This state will never be saved to a file.</summary>
       kProxy,         // File was created on a newer Desktop.
       ///<summary>Database contains more than one part, no components. (Legacy data.)</summary>
       kMultiPart,     // Database contains more than one part, no components. (Legacy data.)
       ///<summary>Database contains both components and parts.(Legacy data.)</summary>
       kMixed,         // Database contains both components and parts.(Legacy data.)
       ///<summary>No Parts or Components in file.</summary>
       kForeign,       // No Parts or Components in file
       ///<summary>MDT APP's not loaded, file state undeterminable.</summary>
       kUnknown        // MDT APP's not loaded, file state undeterminable
    };

    ///<summary>DwgType identifies the content of the drawing.</summary>
    enum DwgType {
      ///<summary>AutoCAD</summary>
      kAcad = 0,                          // AutoCAD
      ///<summary>AutoCAD Mechanical</summary>
      kAcadM = 2,                         // AutoCAD Mechanical
      ///<summary>AutoCAD Mechanical Structure</summary>
      kAcadMStruct = 3,                   // AutoCAD Mechanical Structure
      ///<summary>MDT Assembly</summary>
      kMDT = 4,                           // MDT Assembly
      ///<summary>MDT Part</summary>
      kMDTPart = 5,                       // MDT Part
      ///<summary>Inventor Link</summary>
      kInventorLink = 6,                  // Inventor Link
      ///<summary>Undefined Drawing Type</summary>
      kUndefined = 7                      // Undefined Drawing Type
    };

    enum DesignModeType
    {
        ///<summary>Developing the model whether assembly or part</summary>
        kModelMode,       // Developing the model whether assembly or part
        ///<summary>Creating drawings</summary>
        kDrawingMode,     // Creating drawings
        ///<summary>Creating scenes for assemblies</summary>
        kSceneMode,       // Creating scenes for assemblies
        ///<summary>when there is no database</summary>
        kUninitialized    // when there is no database
    };

    ///<summary><para>AttributeDataType Used to specify a descriptor attribute data type.</para><para>For internal
    ///use only.</para></summary>
    enum AttributeDataType
    {
        attTypeInt        =   0,
        attTypeDouble     =   1,
        attTypeCharPtr    =   2,
        attTypeEnum       =  10,
        attTypePoint3d    =  50,
        attTypeMatrix3d   =  51,
        attTypeEntity3d   =  55,
        attTypeObjKey     =  70,
        attTypeValue      =  71,
        attTypeSelection  =  72,
        attTypeExternalId =  80,
        attTypeSpecial    =  9999
    };

    ///<summary>AttSpecialValues used to pass special values as function arguments.</summary>
    enum AttSpecialValues
    {
        ///<summary>NAV:  Not A Value</summary>
        attNAV      = 1         // NAV:  Not A Value
    };


    ///<summary>Axis direction.</summary>
    enum AxisDirType
    {
        ///<summary>Positive X direction.</summary>
        kPositiveX = 1,
        ///<summary>Negative X direction.</summary>
        kNegativeX = 2,
        ///<summary>Positive Y direction.</summary>
        kPositiveY = 3,
        ///<summary>Negative Y direction.</summary>
        kNegativeY = 4,
        ///<summary>Positive X direction.</summary>
        kXAxisPos       = kPositiveX,
        ///<summary>Negative Y direction.</summary>
        kYAxisNeg       = kNegativeY,
        ///<summary>Negative X direction.</summary>
        kXAxisNeg       = kNegativeX,
        ///<summary>Positive Y direction.</summary>
        kYAxisPos       = kPositiveY
    };

    ///<summary>Enumeration of geometry reference orientation.</summary>
    enum NormalOrientnType
    {
      kRaw,
      kReversed
    };
};

typedef Ami::FlatStatus            AmiFlatStatus;
typedef Ami::KeyType               AmiKeyType;
typedef Ami::DesignEnvironmentType AmiDesignEnvironmentType;
typedef Ami::DesignModeType        AmiDesignModeType;
typedef Ami::DwgType               AmiDwgType;
typedef Ami::AttributeDataType     AmiAttributeDataType;
typedef Ami::AxisDirType           AmiAxisDirType;
typedef Ami::NormalOrientnType     AmiNormalOrientnType;



typedef Adesk::UInt32 AmiObjectState;

#define AMI_STATE_USERCREATED   0x01



#define AMI_INVALID_KEY ((unsigned) -1)



///<summary>MCAD API pick object.</summary>
class AMIAPI AmiPickObj
{
  public:
    AmiPickObj() : mpData(NULL) {}
   ~AmiPickObj();

    void* mpData;
};

#pragma warning( disable : 4251 4275 )

///<summary>Base mcadapi object class.</summary>
class AMIAPI AmiObjectBase : public AcRxObject
{
  public:

    MCADAPI_DECLARE_MEMBERS(AmiObjectBase);

    ///<summary>Functions increment the object reference count. When a reference count decrement causes the count
    ///to hit zero, the object deletes itself.</summary>
    virtual unsigned addRef ();
    ///<summary>Functions decrement the object reference count. When a reference count decrement causes the count 
    ///to hit zero, the object deletes itself.</summary>
    virtual unsigned release();
    ///<summary>Functions return the object reference count. When a reference count decrement causes the count to
    ///hit zero, the object deletes itself.</summary>
    virtual unsigned refCnt () const;
	virtual Acad::ErrorStatus copyFrom(const AcRxObject* other);

  protected:

    ///<summary>Class constructor.</summary>
    AmiObjectBase() : mcRef   (1),
                      mOwnerId(UNSET_APP_ID),
                      mpData  (NULL),
                      mpDoc   (NULL)
                      {}

  public:

    unsigned mcRef;          // Object reference count.
    AmiAppId mOwnerId;       // Object owner identification.
    void*    mpData;         // Pointer to object implementation.
    void*    mpDoc;          // Doc pointer (transient, not written to DWG).
};

///<summary>Base object key class.</summary>
class AMIAPI AmiObjectKey : public AmiObjectBase
{
  public:

    MCADAPI_DECLARE_MEMBERS(AmiObjectKey);

    ///<summary>Functions increment the key reference count. When a reference count decrement causes the count to
    ///hit zero, the erases and deletes itself.</summary>
    virtual unsigned addRef ();
    ///<summary>Functions decrement the key reference count. When a reference count decrement causes the count to
    ///hit zero, the erases and deletes itself.</summary>
    virtual unsigned release();
    ///<summary>Functions return the key reference count. When a reference count decrement causes the count to hit
    ///zero, the erases and deletes itself.</summary>
    virtual unsigned refCnt () const;

    ///<summary>Functions increment the key persistent reference count.</summary>
    virtual unsigned addPersistentRef(AcDbObject* pRefferingObj);
    ///<summary>Functions return the key persistent reference count.</summary>
    virtual unsigned persistentRefCnt() const;
    ///<summary>Functions decrement the key persistent reference count.</summary>
    virtual unsigned erase(bool fErasing = true);

    AcDbObjectId mPersKey;

  protected:

    ///<summary>Class constructor.</summary>
    AmiObjectKey() {}

    friend class AmiDocInfo;
};

///<summary><para>Base descriptor class definition.</para><para>The descriptor holds a void-ptr to internal
///implementation of descriptor classes.</para><para>Objects of this class are NOT persistent.</para></summary>
class AMIAPI AmiDescrip : public AmiObjectBase
{
  public:
    MCADAPI_DECLARE_MEMBERS(AmiDescrip);

    ///<summary>Release method for descriptors decrements the reference count and, in the event that the count
    ///hits zero, calls the owning application's function to clean up the descriptor.</summary>
    virtual unsigned release();
};

#define SET_STRUCTURE_MODE_EDIT_ENTITY                                    \
  AmiStructApiAccess oStructApiAcc;                                       \
  oStructApiAcc.setStructApiMode(true);                                   \
  if (!oStructApiAcc.isInStructApiMode())                                 \
  {                                                                       \
    AmiStatus status(Ami::kSetStructModeEditEntityError, Ami::kError);    \
    acutPrintf(ACRX_T(/*MSG0*/"%s\n"), status.text().c_str());            \
  }

///<summary>Class sets the editor state to be in the Structure API mode.</summary>
class AMIAPI AmiStructApiAccess
{
public:
  ///<summary>Class constructor.</summary>
  AmiStructApiAccess();
  ///<summary>Class destructor.</summary>
  virtual ~AmiStructApiAccess();

public:
  ///<summary>Sets the editor state to Structure API mode.</summary>
  void setStructApiMode(bool bMode);
  ///<summary>Checks if the editor state is in Structure API mode.</summary>
  bool isInStructApiMode();

private:
  void setStructApiRef(bool bRef);
  bool isRefByStructApi();
  void openOuterTrans();
  void closeOuterTrans();

  void validateDoc();
  void clear();

private:
  AcMeDoc* mpDoc;
  bool mbSetStructApiRef;
  bool mbSetStructApiMode;
  bool mbClosedOuterTrans;
};

typedef AmiArray<AmiObjectBase> AmiObjectBaseArray;
typedef AmiArray<AmiObjectKey>  AmiObjectKeyArray;
typedef AmiArray<AmiDescrip>    AmiDescripArray;

#define AMI_NULLOBJKEYREF *((AmiObjectKey**) NULL)

typedef void (*AmiNullFuncPtr) ();

typedef void (*AmiNotifFcnPtr ) (AmiObjectKey* pObjectKey);
typedef void (*AmiNotifFcnPtr2) (AmiObjectKey* pObjectKey, AcDbObjectId id);

///<summary>Returns the database which is actively being editted.  This
///              will change as the document changes and as external databases
///              are editted locally (xref edit).</summary>
AMIAPI AmiStatus amiGetCurrentDatabase( AcDbDatabase*& pDb );

///<summary>Returns the information from the specified pick object.</summary>
///<param name="pPickObj">Pick object to retrieve information from.</param>
///<param name="subentPath">Full sub entity path of pick.</param>
///<param name="pickPoint">Pick point.</param>
///<param name="pickVector">Pick vector.</param>
///<param name="viewTrans">View transformation matrix.</param>
///<param name="isGhost">True if geometric resolution is possible even
///                           after the entity has dissappeared.</param>
AMIAPI AmiStatus amiGetPickInfo( AmiPickObj* pPickObj, AcDbFullSubentPath& subentPath,
								 AcGePoint3d& pickPoint, AcGeVector3d& pickVector,
								 AcGeMatrix3d& viewTrans, Adesk::Boolean& isGhost );

///<summary>Converts a subent path from graphical to logical or from
///              logical to graphical. In the pure MCADAPI, object keys
///              mainly refer to logical (or database) entities. Within MDT,
///              many of these database entities of graphical (displayable)
///              counterparts. When using objectDBX to perform picking, the
///              subent path's usually refer to the graphical entities. This
///              utility function can be used to convert those subent paths
///              to refer to logical entities or, if a subent path already
///              refers to the logical entity, this function can convert it
///              to refer to the graphical entities.
///
///              NOTE: If a subent already refers to the entity that the
///                    function is asked to convert to, the subent will come
///                    back unchanged.</summary>
///<param name="subentPath">The subent path to convert.</param>
///<param name="toLogical">If true, converts the subent path to refer to
///                           the logical entity. If false, converts the path
///                           to refer to the graphical entity.</param>
///<param name="subentPath">Input subent path is returned converted.</param>
AMIAPI AmiStatus amiConvertPath( AcDbFullSubentPath& subentPath,
								 Adesk::Boolean toLogical = Adesk::kTrue );

///<summary>Checks whether the given object keys has been initialized.</summary>
///<param name="pObjKey">A pointer to an object key.</param>
///<param name="nullKey">A value of true if the key is null;
///                        otherwise, it is false.</param>
AMIAPI AmiStatus amiIsKeyNull( AmiObjectKey* pObjKey, Adesk::Boolean& nullKey );

///<summary>Returns the type of the specified key.</summary>
///<param name="pObjKey">A pointer to a key.</param>
///<param name="type">The type of the key.</param>
AMIAPI AmiStatus amiGetKeyType( AmiObjectKey* pObjKey, AmiKeyType& type );

///<summary>Checks if the type of the key is derived from or the same as
///              type.</summary>
///<param name="pObjKey">The pointer to a key type.</param>
///<param name="type">The type to check against.</param>
///<param name="isType">A value of true if the key is of the same type as type or
///                        if the key type is derived from type; otherwise, isType
///                        is false.</param>
AMIAPI AmiStatus amiIsKeyKindOf( AmiObjectKey* pObjKey, AmiKeyType type,
								 Adesk::Boolean& isType );

///<summary>Reads a key from a given filer. This function is usually called
///              from the dwgin method of the application object that owns the
///              key.  It is the callers responsibility to release the key.</summary>
///<param name="filer">A pointer to the filer.</param>
///<param name="pFilingObj">The filing database object.</param>
///<param name="pObjKey">The pointer to the key.</param>
AMIAPI AmiStatus amiReadKey( AcDbDwgFiler* filer, AcDbObject* pFilingObj,
							 AmiObjectKey*& pObjKey );

///<summary>Writes the key to the given filer. This function is usually
///              called from the dwgout method of the application object that
///              owns the key.</summary>
///<param name="filer">A pointer to the filer.</param>
///<param name="pFilingObj">The filing database object.</param>
///<param name="pObjKey">The pointer to the key.</param>
AMIAPI AmiStatus amiWriteKey( AcDbDwgFiler* filer, AcDbObject* pFilingObj,
							  AmiObjectKey* pObjKey );

///<summary>Creates a geometric key from the given object id.  If an
///              error occurs a bad status is returned and pGeomKey is set to
///              NULL.  It is the caller's responsibility to release the key.</summary>
///<param name="id">The object id from which the geom key is created.</param>
///<param name="type">indicates what kind of key to create.</param>
///<param name="inferFlag">indicates whether or not to infer a key.</param>
///<param name="pSubId">An optional subentity from which to create the key.</param>
///<param name="pPoint">An optional point to clarify how the key should be
///                     created.</param>
///<param name="pObjectKey">a pointer to the key.</param>
AMIAPI AmiStatus amiGetKeyFromId( AcDbObjectId id,
								  AmiKeyType type, AmiObjectKey*& pObjectKey,
								  Adesk::Boolean inferFlag = Adesk::kTrue,
								  AcDbSubentId* pSubId = NULL,
								  AcGePoint3d* pPoint = NULL );

///<summary>Creates an object key from the given subentity path.
///              The key will refer to the subentity identified by the subentPath,
///              if any.  If no subentity is identified, the key will refer to
///              the entity itself.  If the entity's id is not contained in the
///              AcDbFullSubentPath, an error is returned.  If an error occurs
///              a bad status is returned and pObjectKey is set to NULL.  It is
///              the caller's responsibility to release the key.</summary>
///<param name="subentPath">The subentPath from which the object key is created.</param>
///<param name="type">Indicates what kind of key to create.</param>
///<param name="inferFlag">Indicates whether or not to infer a key.</param>
///<param name="pPoint">An optional point to clarify how the key should be
///                         created.</param>
///<param name="pObjectKey">a pointer to the key.</param>
AMIAPI AmiStatus amiGetKeyFromPath( const AcDbFullSubentPath& subentPath,
								    AmiKeyType type, AmiObjectKey*& pObjectKey,
								    Adesk::Boolean inferFlag = Adesk::kTrue,
								    AcGePoint3d* pPoint = NULL );

///<summary>Creates a new key from pObjKey which refers to the equivalent
///              object to that referred to by pObjKey at the scope implied by
///              pRefKey. For example, if one has a line key to the boundary of a
///              part, it is possible, using this function, to obtain a key to the
///              same line in the scope of an instance of that part in an assembly
///              and vice-versa. If there is no equivalent entity in the scope
///              of pRefKey, amiRefocusKey returns eUnmatchedLeafObject.</summary>
///<param name="pObjKey">Pointer to key to be refocused. Only geom Keys and
///                          feature keys are supported.</param>
///<param name="pRefKey">Pointer to key to object that specifies desired
///                          focus (currently only leaf component, part, geometry
///                           and feature keys supported).</param>
///<param name="pNewObjKey">Key created which references the equivalent
///                          object as pObjKey in the scope of pRefKey.</param>
AMIAPI AmiStatus amiRefocusKey( AmiObjectKey *pObjKey, AmiObjectKey *pRefKey,
							    AmiObjectKey *&pNewObjKey = AMI_NULLOBJKEYREF );

///<summary>Copies the given key and returns another key that resolves to the
///              same application object as the original key.   It is the caller�s
///              responsibility to release the key.</summary>
///<param name="pObjKey">A pointer to original key.</param>
///<param name="pTargetDatabase">The database into which the key is copied</param>
///<param name="pCopy">A pointer to copy of the key.</param>
AMIAPI AmiStatus amiCopyKey( AmiObjectKey* pObjKey, AmiObjectKey*& pCopy,
							 AcDbDatabase* pTargetDatabase = NULL );

///<summary>Fills data fields of pick object, given a result buffer in the
///              format returned by ads_ssnamex() and the type of key to be created
///              usingpickObj. Note that, when set to Adesk::kTrue, the allowGhost
///              flag is effective only for AutoCAD Designer edges or vertices.</summary>
///<param name="pickResBuf">A resbuf that contains pick information as
///                           formatted and returned by ads_ssnamex().</param>
///<param name="type">The type of the key that the caller creates. An
///                           abstract type can be used.  Not all concrete
///                           types are supported (e.g. compKey, dwvwKey,
///                           dwLayoutKey, and sceneKey are not supported).</param>
///<param name="allowGhost">A value of true when the caller wants resolution
///                           even if entity has disappeared, for example,
///                           resolution to an edge that has been chamfered.</param>
///<param name="pickObj">An object with all of its data fields filled that
///                           represents the object picked by the user.  This
///                           object selected by the user.</param>
AMIAPI AmiStatus amiFillPickObj( struct resbuf* pickResBuf,
								AmiKeyType type, AmiPickObj& pickObj,
								Adesk::Boolean allowGhost = Adesk::kFalse );

///<summary><para>Get an object key based on an object name.</para>
///
///          <para>Given an object name, this function attempts to create a
///              key of the given key type. The scope key is used to determine
///              the starting point where to look for the object. For example,
///              given a key type of "Ami::featKey" and a part key as the scope,
///              the function will look for a feature within that part with the
///              given name and create a feature key to that feature. If the
///              scope key is NULL, it is assumed that we're looking for an
///              object in the global scope such as a part or component
///              definition.</para>
///
///        <para>Currently, this function is only implemented to create
///              feature, parameter, or sketch keys. The feature and sketch
///              key creation requires a part key as the scope key. The
///              parameter key creation will work with a part key or a NULL
///              key (global parameter).</para>
///<param name="name">Name of object to get key for.</param>
///<param name="keyType">Type of key that is to be created.</param>
///<param name="pScopeKey">Key to scope object.</param>
///<param name="appName">Application to create key.</param>
///<param name="pKey">Pointer to created key.</param>
AMIAPI AmiStatus amiGetKeyFromName( const ACHAR* name,
								    AmiKeyType keyType, AmiObjectKey*& pKey,
								    AmiObjectKey* pScopeKey = NULL, const ACHAR* appName = NULL);

///<summary>Tag the internal state of the specified MDT object to indicate
///              that the object is not up-to-date and requires regeneration.</summary>
///<param name="pKey">Pointer to an object key.</param>
AMIAPI AmiStatus amiSetNeedsRegen( AmiObjectKey* pKey );


AMIAPI AmiStatus amiRegenAllOfAType(Ami::KeyType objType, Adesk::Boolean fForce = Adesk::kFalse);

///<summary>This function get the Document associated with the key.
///              Every key is associated with at most one document.</summary>
///<param name="pAmiBase">pointer to an MCADAPI object (e.g. a key).</param>
///<param name="pDoc">pointer to document associated with input argument.</param>
AMIAPI AmiStatus amiGetAssociatedDoc( AmiObjectBase* pAmiObject,
                   AcApDocument*& pDoc );

extern AmiStatus AMIAPI amiGetAssociatedDbs( AmiObjectKey* pObjKey,
                                             INT_PTR &numDatabases,
                                             AcDbDatabase**& pDbs );

///<summary>Creates an object key from a pick object and returns the type
///              of key created. If an error occurs a bad status is returned
///              and pObjKey is set to NULL. It is the caller�s responsibility
///              to release the key.</summary>
///<param name="pPickObj">The pointer to the pick object.</param>
///<param name="type">The type of the key that was created.</param>
///<param name="pObjKey">The pointer to the key.</param>
AMIAPI AmiStatus amiGetKeyFromPick( AmiPickObj* pPickObj,
                   AmiKeyType& type, AmiObjectKey*& pObjKey );

///<summary>Compares two keys to determine if they refer to the same entity.
///              The pKey1 parameter points to the first object key.  The pKey2
///              parameter points to second object key.  When the function
///              returns, the areEquivalent parameter is true if the keys resolve
///              to the same entity; otherwise, it is false.  The considerComp
///              parameter allows you to determine not only whether the geometry
///              or features of two keys are equivalent, but also whether they are
///              located on the same component.  The two keys must resolve to the
///              same lowest-level component to be equal.  The differsInCompOnly
///              parameter allows you to determine whether the difference between
///              keys is caused solely by location on different components.
///              Note also that considerComp is applicable only to component keys,
///              geometry keys and feature keys.  It is ignored (differsInCompOnly
///              returns false) for part, constraint, parameter, sketch, solid and
///              component definition keys.</summary>
///<param name="pKey1">pointer to first object key.</param>
///<param name="pKey2">pointer to second object key.</param>
///<param name="considerComp">If true, the equivalence test considers the
///                                  component as a criterion for determining if
///                                  the keys are equivalent. If false, the
///                                  component is not considered.  In other words,
///                                  if true,two keys must not only refer to the
///                                  same geometry or feature to be equivalent,
///                                  but they must also be on the same component.
///                                  If false, two keys referring to the same
///                                  geometry or feature will return true
///                                  regardless of the component.</param>
///<param name="areEquivalent">A value of true if the keys resolve to the
///                              same entity; otherwise, it is false.</param>
///<param name="differsByCompOnly">If a pointer to a boolean is specified
///                                  here, the result will tell whether
///                                  the keys are not equivalent only
///                                  because they are located on different
///                                  components. This is independant of the
///                                  considerComp argument and is ignored if
///                                  a NULL pointer is specified.</param>
AMIAPI AmiStatus amiAreKeysEquivalent( AmiObjectKey* pKey1,
							   AmiObjectKey* pKey2, Adesk::Boolean& areEquivalent,
							   Adesk::Boolean considerComp = Adesk::kTrue,
							   Adesk::Boolean* differInCompOnly = NULL);

///<summary>Checks if the object referenced by pObjKey has been erased.
///              Currently supported for all keys.</summary>
///<param name="pKey">A pointer to the object key.</param>
///<param name="erased">A value of true if the application object was erased;
///                        otherwise, it is false.</param>
AMIAPI AmiStatus amiObjectWasErased( AmiObjectKey* pKey, Adesk::Boolean& erased );

///<summary>Prompts user to perform a single pick and fills the pick
///              object data fields. The pick object (pickObj) can be used in
///              creating a key to the object picked by the user. Note that, when
///              set to Adesk::kTrue, the allowGhost flag is effective only for
///              AutoCAD Designer edges or vertices.</summary>
///<param name="prompt">The prompt displayed to the user.</param>
///<param name="type">The type of key that the caller intends to create.
///                           An abstract type can be used.</param>
///<param name="entmask">The kind of result-buffer list that ads_ssget() uses
///                           to filter a drawing to select particular entities.</param>
///<param name="allowGhost">A value of true when the caller wants resolution
///                           even if the entity has disappeared, for example,
///                           resolution to an edge that has been chamfered.</param>
///<param name="activeInstance">A value of true restricts the picking to the currently
///                           active part instance (if valid for the specified key type).</param>
///<param name="keyWords">A list of keywords seperated by spaces.</param>
///<param name="defaultKeyWord">specify a default, use NULL for NO default keyword</param>
///<param name="includeInList">true indicates that the default keyword is added to the main list
///                            false indicates that the default keyword is not added to the list</param>
///<param name="pickObj">An object with all of its data fields filled that
///                           represents the object picked by the user.  This
///                           construct can then be used to create a key to the
///                           object picked by the user.</param>
///<param name="keyWordUsed">The keyword that the user accepted.  This argument
///                           is only filled when the return status is kKeyWord.
///                           The user is responsible for releasing the memory
///                           used by keyWordUsed.</param>
AMIAPI AmiStatus amiPick(const ACHAR* prompt, Ami::KeyType type,
                   struct resbuf* entmask, AmiPickObj& pickObj,
                   Adesk::Boolean allowGhost,
				   Adesk::Boolean activeInstance,
				   const ACHAR* keyWords, const ACHAR* defaultKeyWord,
                   Adesk::Boolean includeInList,
                   ACHAR** keyWordUsed);

AMIAPI AmiStatus amiPick (  const ACHAR* prompt, Ami::KeyType type,
                            struct resbuf* entmask, AmiPickObj& pickObj,
                            Adesk::Boolean allowGhost = Adesk::kFalse,
				                    Adesk::Boolean activeInstance = Adesk::kFalse,
				                    const ACHAR* keyWords = NULL, ACHAR** keyWordUsed = NULL) ;

///<summary>Highlights or turns off highlighting of the entity referred to by pObjKey.</summary>
///<param name="pObjKey">Pointer to key.</param>
///<param name="highlight">A value of true to highlight the entity referred
///                            to by pObjKey or false to turn off highlighting
///                            for the entity.</param>
///<param name="scaleFactor">A value applied to the default size of
///                            graphics used in highlighting unbounded or
///                            inferred entities.</param>
AMIAPI AmiStatus amiHighlight( AmiObjectKey* pObjKey, Adesk::Boolean highlight, double scaleFactor = 1.0 );

///<summary>Erases the object referenced by the key, if allowed.</summary>
///<param name="pObjKey">Pointer to the key.</param>
AMIAPI AmiStatus amiEraseObject ( AmiObjectKey* pObjKey );

///<summary>Returns an array of AcDbObjectId's corresponding to the given
///              object key. It is not guaranteed to work for all key types.
///              It is the caller�s responsibility to delete the array.</summary>
///<param name="pObjKey">Pointer to key.</param>
///<param name="numIds">Number of DbId's in pIdsArray.</param>
///<param name="pIdsArray">Array of DbId's (to be deleted by caller)</param>
AMIAPI AmiStatus amiGetDbIdsFromKey( AmiObjectKey* pObjKey,
                   int& numIds, AcDbObjectId*& pIdsArray );

///<summary>Retrieves the name for the object specified by the
///              object key. The user is responsible for releasing the
///              memory used by objName.</summary>
///<param name="pObjKey">The pointer to the object key.</param>
///<param name="objName">Name of object of the given key.</param>
AMIAPI AmiStatus amiGetObjectName(AmiObjectKey* pObjKey, ACHAR*& objName);

///<summary>Sets the name for the object specified by the object
///              key. An error is returned if the name is the same as
///              that of another object of the same type. This function is
///              currently implemented for feature keys only.</summary>
///<param name="pObjKey">The pointer to the object key.</param>
///<param name="objName">New name for the object.</param>
AMIAPI AmiStatus amiSetObjectName(AmiObjectKey* pObjKey, const ACHAR* objName);

///<summary>Checks if the object referred to by the specified key is
///              directly editable.</summary>
///<param name="pObjKey">Pointer to object key.</param>
///<param name="editable">true, object is directly editable.
///                         false, otherwise.</param>
AMIAPI AmiStatus amiIsDirectlyEditable( AmiObjectKey* pObjKey,
                   Adesk::Boolean& editable );

///<summary>Regenerates the specified MDT object.  If the object has been
///              marked for update, then this function will regen the object.
///              The force-flag can be used to force a regen.
///              This function does not necessarily update the display to
///              bring it in sync with the object (update of the displayed
///              graphics is often done at end-of-command following a regen).
///              Not all objects can be regenerated directly.  For example,
///              amiRegen() returns eNotApplicable for feature keys and
///              constraint keys.  Instead, the part or assembly should be
///              regenerated with respect to these objects.</summary>
///<param name="pKey">Pointer to an object key.</param>
///<param name="fForce">Force regen even if internal states indicates that
///                     regeneration is not necessary (i.e. object not marked
///                     for update).</param>
AMIAPI AmiStatus amiRegen( AmiObjectKey* pKey, Adesk::Boolean fForce = Adesk::kFalse );

///<summary><para>Retrieves the state for the object specified by the
///              object key. Macros can be used to retrieve the specific
///              attributes packed into the state.</para>
///
///         <para>Not all types of keys are supported at this time.  Currently,
///              the following types of keys are supported: parts, features,
///              and parameters.</para>
///         <para>Features and parts are also supported by the older functions,
///              amiGetFeatState() and amiGetPartState().  Eventually, these
///              functions will be replaced with amiGetObjectState().</para></summary>
///<param name="pObjKey">The pointer to the object key.</param>
///<param name="objState">Bit packed representation of the object state
///                         The state attribute location is dependent on the type
///                         of key used.  These locations are defined by macros
///                         in the header files, where these macros are all
///                         prefixed with "AMI_STATE_".</param>
AMIAPI AmiStatus amiGetObjectState(AmiObjectKey* pObjKey, AmiObjectState& objState);

///<summary><para>Gets the visibility of the object referenced by the given key.
///              This function is not implemented for all types of keys.</para>
///
///              <para>NOTE: Currently, this function only works on:
///                          Components (AmiCompKey)
///                          Work features (AmiFeatKey, AmiGeomKey)</para>
///
///              <para>NOTE: For comp keys, the key must be for a "comp in def".
///                    In other words, visibility is a property of only those
///                    comps that are not contained within other comps.
///                    The function, amiGetCompInDef() can be used to convert
///                    a comp key to one that meets this criterion.</para></summary>
///<param name="pObjKey">Pointer to an object key.</param>
///<param name="bVisibilityOn">kTrue if and only if the underlying object
///                    has not had visibility turned off.</param>
AMIAPI AmiStatus amiGetObjectVisibility(AmiObjectKey* pObjKey,
                                 Adesk::Boolean& bVisibilityOn);

///<summary><para>Sets the visibility of the object referenced by the given key.
///              This function is not implemented for all types of keys.</para>
///
///              <para>NOTE: Currently, this function only works on:
///                          Components (AmiCompKey)
///                          Work features (AmiFeatKey, AmiGeomKey)</para>
///
///              <para>NOTE: For comp keys, the key must be for a "comp in def".
///                    In other words, visibility is settable on only those
///                    comps that are not contained within other comps.
///                    The function, amiGetCompInDef() can be used to convert
///                    a comp key to one that meets this criterion.</para></summary>
///<param name="pObjKey">Pointer to an object key.</param>
///<param name="bVisibilityOn">the desired visibility setting for the object.</param>
AMIAPI AmiStatus amiSetObjectVisibility(AmiObjectKey* pObjKey,
                  Adesk::Boolean bVisibilityOn);

///<summary>Returns the type of drawing for the specific database.</summary>
AMIAPI AmiStatus amiGetDrawingType( AcDbDatabase * pDb, AmiDwgType &value );

///<summary>Fills in graph with a completed graph of xrefs in the database pointed to by pHostDb.
///              This graph will not contain the temporary xref connections that ACM/MDT forms. Refer
///              to object arx documentation on acdbGetHostDwgXrefGraph for more information on the parameters.</summary>
AMIAPI Acad::ErrorStatus amiGetHostDwgXrefGraph( AcDbDatabase *  pHostDb,
												 AcDbXrefGraph & graph,
												 Adesk::Boolean  includeGhosts = Adesk::kFalse);

#endif  // AMIBASE_H
