//////////////////////////////////////////////////////////////////////////////
//
//  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.   
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include "AdAChar.h"

class AcmStandard;
class AcmSymbolStd;
class AcmStdReactor;

///<summary>AcmStandardManager is responsible to provide access to overall standard functionality, to provide
///a bridge between AcmStandard related classes and AcmSymbol related classes. For example, when creating a 
///welding symbol, an AcmWelding object asks the AcmStandardManager for the connection to a standard object so 
///that AcmWelding object does not need to know where this standard object is located when attaching a
///new symbol standard.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmStandardManager : public AcRxService
{
public:
  ACRX_DECLARE_MEMBERS(AcmStandardManager);
  ///<summary>Returns the name of the default standard.</summary>
  virtual void             getDefaultStd(CString& stdName) const = 0;
  ///<summary>Provides the general interface for editing settings of standards. Displays a list of installed
  ///standards (ARX definition) and currently presented standards in the drawing file. Then it is possible
  ///to call edit member functions for each standard presented in a drawing.</summary>
  virtual Adesk::Boolean   edit(CWnd* pParentWnd = NULL) = 0;
  ///<summary>Sets the current standard using its Id.</summary>
  virtual Acm::ErrorStatus setCurrent(const AcDbObjectId& stdId, AcDbDatabase *pDb  = NULL) = 0;
  ///<summary>Sets the current standard using its Id.</summary>
  virtual Acm::ErrorStatus setCurrent(LPCTSTR name, AcDbDatabase *pDb = NULL) = 0;
  ///<summary>Returns the object id of the current standard or the error code if there is no standard saved
  ///in a drawing.</summary>
  virtual Acm::ErrorStatus getCurrent(CString& name, AcDbDatabase *pDb = NULL, bool bCreate = false) const = 0;
  ///<summary>Returns the object id of the current standard or the error code if there is no standard saved 
  ///in a drawing.</summary>
  virtual Acm::ErrorStatus getCurrent(AcDbObjectId& stdId, AcDbDatabase *pDb = NULL, bool bCreate = true) const = 0;
  ///<summary>Specific interface for adding standards to drawing file.</summary>
  virtual Acm::ErrorStatus addStandard(AcDbObjectId& stdId,
                                       AcmStandard* pNewStd,
                                       Adesk::Boolean setCurrent = Adesk::kTrue,
                                       AcDbDatabase *pDb = NULL) = 0;
  ///<summary>Specific interface for adding standards to drawing file.</summary>
  virtual Acm::ErrorStatus addStandard(AcDbObjectId& stdId,
                                       LPCTSTR pNewStdName,
                                       LPCTSTR pBaseStdName,
                                       Adesk::Boolean setCurrent = Adesk::kTrue,
                                       AcDbDatabase *pDb = NULL) = 0;
  ///<summary>Erases a standard.</summary>
  virtual Acm::ErrorStatus removeStandard(const AcDbObjectId& stdId) = 0;
  ///<summary>Returns the object Id of the standard having the specified name.</summary>
  virtual Acm::ErrorStatus getStd(LPCTSTR pStdName, AcDbObjectId &objId, AcDbDatabase *pDb = NULL) const = 0;
  ///<summary>Fills stdIdArray with all standards in a drawing.</summary>
  virtual Acm::ErrorStatus getStandards(AcDbObjectIdArray& stdIdArray, AcDbDatabase *pDb = NULL) const = 0;
  ///<summary>Fills stdNames with the names of all standards, which are either present in a drawing, or are 
  ///available and can be inserted.</summary>
  virtual Acm::ErrorStatus getAllStandardNames(CStringArray& stdNames) const = 0;
  ///<summary>This member function is not implemented and doesn't return any useful data. You can, however, 
  ///use getStandards and supply an xref database and it will return the list of standards present in the xref database.</summary>
  virtual Acm::ErrorStatus getXRefStandards(CMap<CString,LPCTSTR,AcDbObjectId,const AcDbObjectId&>& stdList) const = 0;
  ///<summary>Fills the arrayOfStandards with pointers to AcRxClass object, derived from base class.</summary>
  ///<param name="baseClass">If empty, AcmStandard is used.arrayOfStandards :</param>
  virtual Acm::ErrorStatus getRegisteredStd(LPCTSTR baseClass,
                                            AcDbVoidPtrArray& arrayOfStandards) const = 0;
  ///<summary>Resets the name of standard.</summary>
  virtual Acm::ErrorStatus renameStd(AcDbObjectId &stdId, const ACHAR* newName) = 0;
  ///<summary>Creates a copy of the standard and sets the given name.</summary>
  virtual Acm::ErrorStatus registerStdBasedOn(const AcDbObjectId &basedStdId,
                                              const ACHAR* stdName,
                                              AcDbObjectId &stdId) = 0;
  ///<summary>Sets the current standard using its Id.</summary>
  virtual Acm::ErrorStatus updateSymbols(AcDbDatabase *pDb = NULL,
                                         AcDbObjectIdArray *pSymStdIdArr = NULL) = 0;
  ///<summary>Returns the number of standards used in the current drawing.</summary>
  virtual int numStandards(AcDbDatabase *pDb = NULL) const = 0;
  ///<summary>Attaches the AcmStandardReactor class to the standard manager.</summary>
  virtual void attachReactor(AcmStdReactor* pReactor) = 0;
  ///<summary>Attaches and detaches the AcmStandardReactor class to the standard manager.</summary>
  virtual void removeReactor(AcmStdReactor* pReactor) = 0;

  ///<summary>Synchronization of current detail/section symbol standards with current detail/section view styles for active standard </summary>
  virtual void synchronizeCurentSymStdAndStyle(AcDbDatabase *pDb = NULL) const = 0;

};

///<summary>A reactor class.</summary>
class ACMSYMBB_CRX_DLLSHARE AcmStdReactor : public AcRxObject
{
public:
  ACRX_DECLARE_MEMBERS(AcmStdReactor);

  ///<summary>Use this callback to populate a standard with your implemented standard.</summary>
  virtual void onNewStandard(AcmStandard *pNewStd) 
  {
		UNREFERENCED_PARAMETER(pNewStd);
  }

  ///<summary>Use this callback to react to changes to the basic standard setting, such as attachment for
  ///lists, units, text height, text style, arrowhead type.</summary>
  ///<param name="var">Specifies which portion of the standard has changed.pSymStd :</param>
  virtual void onChanged(const AcmStandard* pStd, Acm::StdVariable var)
  {
    UNREFERENCED_PARAMETER(pStd);
    UNREFERENCED_PARAMETER(var);
  }

  ///<summary>Use this callback to react to changes to the basic standard setting, such as attachment for 
  ///lists, units, text height, text style, arrowhead type.</summary>
  virtual void onChanged(const AcmSymbolStd* pSymStd)
  {
	  UNREFERENCED_PARAMETER(pSymStd);
  }

  ///<summary>This callback is used to obtain the notification when we are going to remove the standard.</summary>
  virtual void onRemoved(const AcmStandard* pStd)
  {
	  UNREFERENCED_PARAMETER(pStd);
  }

  virtual void onSetCurrentStd(AcDbObjectId& oldCurrentStandard, AcDbObjectId& newCurrentStdId)
  {
	  UNREFERENCED_PARAMETER(newCurrentStdId);
	  UNREFERENCED_PARAMETER(oldCurrentStandard);
	  
  }
  ///<summary>Returns the name of the symbol std that this reactor handles.</summary>
  virtual LPCTSTR symbolStdClassName() const
  { return _T(/*MSG0*/""); }
};

ACMSYMBB_CRX_DLLSHARE AcmStandardManager* getAcmStdMgr();

#define STDMGR_SERVICE_NAME  ACRX_T(/*MSG0*/"AcmStdManagerService")
#define acmStdMgr            getAcmStdMgr()
#define isStdMgrReady()      acrxServiceIsRegistered(STDMGR_SERVICE_NAME)
#define LockStdMgr()         (isStdMgrReady() ? acmStdMgr->addDependency(), TRUE : FALSE )
#define UnlockStdMgr()       (isStdMgrReady() ? acmStdMgr->removeDependency(), TRUE : FALSE )
