/////////////////////////////////////////////////////////////////////////////////////////
//
// Please refer to "COPYRIGHT.md" for the relevant copyright statement of this software.
//
/////////////////////////////////////////////////////////////////////////////////////////
//
#ifndef GCDB_LSTATE_H
#define GCDB_LSTATE_H

#include "dbmain.h"
#include "gcarray.h"
#include "GcString.h"
#include "GcDbCore2dDefs.h"

#pragma pack(push, 8)

class GcDbImpLayerStateManager;
class GcDbLayerStateManagerReactor;

class GCDB_PORT GcDbLayerStateManager : public GcRxObject
{
public:
  GCRX_DECLARE_MEMBERS(GcDbLayerStateManager);
  GcDbLayerStateManager();
  GcDbLayerStateManager(GcDbDatabase* pHostDb);
  ~GcDbLayerStateManager();

  enum LayerStateMask
  {
    kNone = 0x0000,
    kOn = 0x0001,
    kFrozen = 0x0002,
    kLocked = 0x0004,
    kPlot = 0x0008,
    kNewViewport = 0x0010,
    kColor = 0x0020,
    kLineType = 0x0040,
    kLineWeight = 0x0080,
    kPlotStyle = 0x0100,
    kCurrentViewport = 0x0200,
    kTransparency = 0x0400,
    kAll = kOn | kFrozen | kLocked | kPlot | kNewViewport | kColor | kLineType | kLineWeight | kPlotStyle |
           kCurrentViewport | kTransparency,
    kStateIsHidden = 0x8000,
    kLastRestored = 0x10000,
    kDecomposition = kAll | 0x20000
  };

  enum
  {
    kUndefDoNothing = 0,
    kUndefTurnOff = 1,
    kUndefFreeze = 2,
    kRestoreAsOverrides = 4
  };

  bool addReactor(GcDbLayerStateManagerReactor* pReactor);
  bool removeReactor(GcDbLayerStateManagerReactor* pReactor);
  GcDbObjectId layerStatesDictionaryId(bool bCreateIfNotPresent = false);
  bool hasLayerState(const GCHAR* sName);
  Gcad::ErrorStatus saveLayerState(const GCHAR* sName, LayerStateMask mask);
  Gcad::ErrorStatus restoreLayerState(const GCHAR* sName);
  Gcad::ErrorStatus setLayerStateMask(const GCHAR* sName, LayerStateMask mask);
  Gcad::ErrorStatus getLayerStateMask(const GCHAR* sName, LayerStateMask& returnMask);
  Gcad::ErrorStatus deleteLayerState(const GCHAR* sName);
  Gcad::ErrorStatus renameLayerState(const GCHAR* sName, const GCHAR* sNewName);
  Gcad::ErrorStatus importLayerState(const GCHAR* sFilename);
  Gcad::ErrorStatus importLayerState(const GCHAR* sFilename, GcString& sName);
  Gcad::ErrorStatus exportLayerState(const GCHAR* sNameToExport, const GCHAR* sFilename);
  Gcad::ErrorStatus saveLayerState(const GCHAR* sName, LayerStateMask mask, const GcDbObjectId& idVp);
  Gcad::ErrorStatus restoreLayerState(const GCHAR* sName,
                                      const GcDbObjectId& idVp,
                                      int nRestoreFlags = 0,
                                      const LayerStateMask* pClientMask = NULL);
  Gcad::ErrorStatus setLayerStateDescription(const GCHAR* sName, const GCHAR* sDesc);

  Gcad::ErrorStatus getLayerStateDescription(const GCHAR* sName, GcString& sDesc);
#define GcDbLyrStat_Deprecated_GCHAR_Methods
#ifdef GcDbLyrStat_Deprecated_GCHAR_Methods
  Gcad::ErrorStatus getLayerStateDescription(const GCHAR* sName, GCHAR*& sDesc);
#endif
  bool layerStateHasViewportData(const GCHAR* sName);
  Gcad::ErrorStatus importLayerStateFromDb(const GCHAR* pStateName, GcDbDatabase* pDb);
  Gcad::ErrorStatus getLayerStateNames(GcStringArray& lsArray, bool bIncludeHidden = true, bool bIncludeXref = true);
  Gcad::ErrorStatus getLastRestoredLayerState(GcString& sName, GcDbObjectId& restoredLSId);
  Gcad::ErrorStatus getLayerStateLayers(GcStringArray& layerArray, const GCHAR* sName, bool bInvert = false);
  bool compareLayerStateToDb(const GCHAR* sName, const GcDbObjectId& idVp);
  Gcad::ErrorStatus addLayerStateLayers(const GCHAR* sName, const GcDbObjectIdArray& layerIds);
  Gcad::ErrorStatus removeLayerStateLayers(const GCHAR* sName, const GcStringArray& layerNames);
  bool isDependentLayerState(const GCHAR* sName);
  GcDbDatabase* getDatabase() const;

private:
  friend class GcDbImpDatabase;
  friend class GcDbImpLayerStateManager;
  GcDbImpLayerStateManager* mpImpLSM;
};

#ifdef GcDbLyrStat_Deprecated_GCHAR_Methods
inline Gcad::ErrorStatus GcDbLayerStateManager::getLayerStateDescription(const GCHAR* sName, GCHAR*& sDesc)
{
  GcString sRet;
  const Gcad::ErrorStatus es = this->getLayerStateDescription(sName, sRet);
  return ::gcutGcStringToGChar(sRet, sDesc, es);
}
#endif

class GCDB_PORT GcDbLayerStateManagerReactor : public GcRxObject
{
public:
  GCRX_DECLARE_MEMBERS(GcDbLayerStateManagerReactor);
  ~GcDbLayerStateManagerReactor();

  virtual void layerStateCreated(const GCHAR*, const GcDbObjectId&)
  {
  }
  virtual void layerStateCompareFailed(const GCHAR*, const GcDbObjectId&)
  {
  }
  virtual void layerStateToBeRestored(const GCHAR*, const GcDbObjectId&)
  {
  }
  virtual void layerStateRestored(const GCHAR*, const GcDbObjectId&)
  {
  }
  virtual void abortLayerStateRestore(const GCHAR*, const GcDbObjectId&)
  {
  }
  virtual void layerStateToBeDeleted(const GCHAR*, const GcDbObjectId&)
  {
  }
  virtual void layerStateDeleted(const GCHAR*)
  {
  }
  virtual void abortLayerStateDelete(const GCHAR*, const GcDbObjectId&)
  {
  }
  virtual void layerStateToBeRenamed(const GCHAR*, const GCHAR*)
  {
  }
  virtual void layerStateRenamed(const GCHAR*, const GCHAR*)
  {
  }
  virtual void abortLayerStateRename(const GCHAR*, const GCHAR*)
  {
  }
};

#pragma pack(pop)

#endif