#include "externals.hh"
#include "common.hh"

#include "c-filewatcher.hh"
#include "c-opcomp.hh"
#include "c-ops.hh"
#include "c-project.hh"
#include "c-sync.hh"
#include "c-undo.hh"


namespace {

struct CommonData_
{
	T_Project project;
	T_FilesWatcher watcher;
	T_SyncManager sync;
	T_ScriptManager ops;
	T_UndoManager undo;

	CommonData_( T_FSPath const& path ) noexcept
		: project{ path }
	{}
};

uint32_t Initialised_{ 0 };
std::aligned_storage_t< sizeof( CommonData_ ) , alignof( CommonData_ ) > Instance_;

} // namespace <anon>

/*----------------------------------------------------------------------------*/

Common::Common(
		T_FSPath const& path ) noexcept
{
	if ( !Initialised_ ++ ) {
		new ((char*)&Instance_) CommonData_( path );
	}
}

Common::~Common( ) noexcept
{
	assert( Initialised_ );
	if ( !-- Initialised_ ) {
		((CommonData_*)(char*)&Instance_)->~CommonData_( );
	}
}

/*----------------------------------------------------------------------------*/

#define M_ACCESS_() ((CommonData_*)(char*)&Instance_)
#define M_GET_( P ) M_ACCESS_()->P

void Common::SetInteractiveMode( ) noexcept
{
	auto* d{ M_ACCESS_( ) };
	d->sync.enable( );
	d->ops.enable( );
}

/*----------------------------------------------------------------------------*/

T_Project& Common::Project( ) noexcept
	{ return M_GET_( project ); }

T_FilesWatcher& Common::Watcher( ) noexcept
	{ return M_GET_( watcher ); }

T_SyncManager& Common::Sync( ) noexcept
	{ return M_GET_( sync ); }

T_ScriptManager& Common::Ops( ) noexcept
	{ return M_GET_( ops ); }

T_UndoManager& Common::Undo( ) noexcept
	{ return M_GET_( undo ); }