/////////////////////////////////////////////////////////////////////////////
// Name:        No names yet.
// Purpose:     Contrib. demo
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     2000/02/08
// RCS-ID:      $Id: pm_cmn.h,v 1.9 2001/04/03 20:10:26 aleksandras Exp $
// Copyright:   (c) Aleksandras Gluchovas
// Licence:   	GPL (version 2.0 or later)
/////////////////////////////////////////////////////////////////////////////

#ifndef __PM_CMN_G__
#define __PM_CMN_G__

/*=== PMF - Project Management Framework (Tab-size=4) ===*/

// wxWin "rocks" :-)
#include "wx/list.h"
#include "wx/hash.h"
#include "wx/url.h"
#include "wx/dynarray.h"
#include "wx/config.h"
#include "wx/fileconf.h"
#include "wx/mimetype.h"
#include "wx/stream.h"
#include "wx/wfstream.h"

#include "pm_undef.h"

// contribs too...
#include "wx/pmf/keybinder.h"

// class hierarchy 

class wxPMService;

class wxObject;
	class wxPMFileInfo;
	class wxPMFileLoader;
		class wxPMLocalFileLoader;
		class wxPMHTTPFileLoader;
		class wxPMFTPFileLoader;

	class wxPMLayoutPrefs;
	class wxPMBitmapManager;
	class wxPMMergableMenuChain;
	class wxPMMenuTreeItem;

class wxView;
	class wxPMView;

class wxDocument;
	class wxPMDocument;
		class wxPMProject;
		class wxPMWorkplace;

class wxEvtHandler;
		class wxPMBootstrapService;
		class wxPMLayoutAlgorithm;
		class wxPMPane;

class wxDocManager;
	class wxPMDocManager;

class wxPMWorkplaceListener;
class wxPMBootstrapServiceListener;
class wxPMDocumentListener;

// arrays (#ifdef'ed so that their lengthy-decls could be moved
// into precompile-headers for faster compilations)

#ifndef __PMF_ARRAY_TYPES_DEFINED__
#define __PMF_ARRAY_TYPES_DEFINED__

	WX_DEFINE_ARRAY( wxPMProject*,  PMProjectListT );
	WX_DEFINE_ARRAY( wxPMView*,     PMViewListT );
	WX_DEFINE_ARRAY( wxPMDocument*, PMDocumentListT );
	WX_DEFINE_ARRAY( wxPMPane*,     PMPaneListT );
	WX_DEFINE_ARRAY( wxPMService*,  PMServiceListT );
	WX_DEFINE_ARRAY( wxPMFileInfo*, PMFileInfoListT );
	WX_DEFINE_ARRAY( wxClassInfo*,  PMClassInfoListT );
	WX_DEFINE_ARRAY( wxBitmap*,     PMBitmapListT );
	WX_DEFINE_ARRAY( wxPMFileLoader*,		 MPFileLoaderListT );
	WX_DEFINE_ARRAY( wxPMMenuTreeItem*,      PMMenuTreeItemListT );
	WX_DEFINE_ARRAY( wxPMWorkplaceListener*, PMWorkplaceListenerListT );
	WX_DEFINE_ARRAY( wxPMBootstrapServiceListener*, PMBootstrapServiceListenerListT );
	WX_DEFINE_ARRAY( wxPMDocumentListener*, PMDocumentListenerListT );

#endif 

// helper macros for notifying listeners

#define wxPM_NOTIFY_NO_ARG( method ) \
	{ for(size_t ii = 0; ii != m_Listeners.Count(); ++ii )\
		m_Listeners[ii]->##method(); }

#define wxPM_NOTIFY_ONE_ARG( method, arg1 ) \
	{ for(size_t ii = 0; ii != m_Listeners.Count(); ++ii )\
		m_Listeners[ii]->##method( arg1 ); }

#define wxPM_NOTIFY_TWO_ARG( method, arg1, arg2 ) \
	{ for(size_t ii = 0; ii != m_Listeners.Count(); ++ii )\
		m_Listeners[ii]->##method( arg1, arg2 ); }

#define wxPM_NOTIFY_THREE_ARG( method, arg1, arg2, arg3 ) \
	{ for(size_t ii = 0; ii != m_Listeners.Count(); ++ii )\
		m_Listeners[ii]->##method( arg1, arg2, arg3 ); }


class wxPMMergableMenuChain
{
public:
	wxPMMergableMenuChain();
	wxPMMergableMenuChain( const char* predecessorPath, wxCommandInfo* pCommands );

public:
	wxString m_PredecessorPath; // eg. "/&File/&View/&Other Windows/My &Task List/"
							  // NOTE:: path should always be terminated with '/'

	wxCommandInfo* m_pCommands; // array contains wxCommandInfo element with Title=="" as 
							   // indicating the end of array
};

/*
 * Acts as a structure carrying more complete infomration about a 
 * file than it's path name could tell. Is used thought PMF to 
 * provide "location transparency" for it's documents
 *
 * TBD:: add one more ctor which takes wxURL
 */

class wxPMFileInfo : public wxObject
{
public:
	wxPMFileInfo();
	~wxPMFileInfo();

	wxPMFileInfo( const wxPMFileInfo& other );
	const wxPMFileInfo& operator=( const wxPMFileInfo& other );
	bool operator==( const wxPMFileInfo& other ) const;
	
	// ctor
	wxPMFileInfo( const wxString& path );

	virtual void  SetPath( const wxString& path );
	virtual const wxString& GetPath() const;

	// returns MIME type of the file, or empty string if not detected
	virtual const wxString& GetType() const;

	// detects both mime and location types, returns TRUE, if both succeded
	bool DetectType() const; 

	virtual wxString GetNameWithoutPath() const;
	virtual wxString GetPathOnly() const;
	virtual wxString GetNameWithoutExtension() const;
	virtual void ChangeExtension( const wxString newExt );

	virtual wxPMFileLoader* GetFileLoader() const;

	enum GENERAL_FILE_LOCATION_TYPES
	{
		URL_LOCATION = 0,
		ABSOLUTE_LOCAL_FILE,
		RELATIVE_LOCAL_FILE, // TBD:: relative to what?

		UNKNOWN_LOCATION = 100, // the location type is determined by 
							    // analyzing the m_Path string

		// NOTE:: more detailed (specific) type of file's location
		//		  is returned as string by calling GetLocationTypeStr()
		//		  (eg. "FTP_LOCATION", or "HTTP_LOCATION" for URL_LOCATION gen. type)
	};

	virtual int GetLocationType() const;
	virtual wxString GetLocationTypeStr() const;

	// searches list of dynamic classes, finds all derivatives 
	// of wxPMFileLoader, instantiates and registers them

	static void RegisterLoaders();

	/*** static methods ***/

	static void RegisterFileLoader( wxPMFileLoader* pLoader );

	// similar to wxMimeTypesManager::AddFallbacks of 2.1.11,
	// added to enable compatibilitiy with earlier wxWin versions (eg. 2.0.1)
	// which doesn't have it

	static void RegisterTypeFallback( const wxString& mimeType, const wxString& ext );
	static wxString FindFallBackForExtention( const wxString& ext );

	static void RegisterDefaultTypeFallbacks();

	static wxString GetDirectoryFromPath( const wxString& path );
	static bool CreateDirsForPath( const wxString& path );

	DECLARE_DYNAMIC_CLASS( wxPMFileInfo )

protected:
	wxString    m_Path;

	mutable wxString        m_Type;    // mime-type
	mutable wxPMFileLoader* m_pLoader; // refers to element of m_RegisteredLoaders
	mutable wxPMFileLoader* m_pLoaderProto; // prototype, from which the actual m_pLoader
										   // will be produced

	static wxMimeTypesManager* msMimeMgr;		 // FIXME:: memory-leak
	static MPFileLoaderListT   msRegisteredLoaders; // FIXME:: more memory-leaks
};

/*
 * base class for all specific file-loaders (HTTP/FTP/loca/etc)
 *
 * NOTE:: All derivatives of wxPMFileLoader have to be delcared
 *        as dynamic classes, this way theye are automatically
 *        registered and found by wxPMFileInfo during auto-detection
 *		  of file locations.
 */

class wxPMFileLoader : public wxObject
{
public:
	wxPMFileLoader();

	virtual void SetFileInfo( wxPMFileInfo* pInfo );
	virtual wxPMFileInfo* GetFileInfo();

	// overridables for concrete file-loaders (all of them should be overriden!)

	virtual wxPMFileLoader* Clone();

	virtual bool CanAcceptPath( const wxString& path );

	virtual bool CreateDirsForPath();

	virtual bool FileExists();
	virtual bool CanWrite();

	virtual wxInputStream* GetInputStream();
	virtual wxOutputStream* GetOutputStream();

	virtual bool IsOpen();
	virtual bool Close();

	virtual int GetLocationType();
	virtual wxString GetLocationTypeStr();


	DECLARE_CLASS( wxPMFileLoader )

protected:
	wxPMFileInfo* m_pFileInfo; // can be NULL, if this instance serves
							  // only for registration
};

class wxPMLocalFileLoader : public wxPMFileLoader
{
public:
	wxPMLocalFileLoader();
	~wxPMLocalFileLoader();

	// overriden methods of wxPMFileLoader
	virtual wxPMFileLoader* Clone();
	virtual bool CanAcceptPath( const wxString& path );

	virtual bool CreateDirsForPath();

	virtual bool FileExists();
	virtual bool CanWrite();

	virtual wxInputStream* GetInputStream();
	virtual wxOutputStream* GetOutputStream();

	virtual bool IsOpen();
	virtual bool Close();

	virtual int GetLocationType();
	virtual wxString GetLocationTypeStr();

	DECLARE_DYNAMIC_CLASS( wxPMLocalFileLoader )

protected:
	wxFileInputStream* m_pInputStream;
	wxFileOutputStream* m_pOutputStream;
};

class WXDLLEXPORT wxFTP;
class WXDLLEXPORT wxHTTP;

class wxPMHTTPFileLoader : public wxPMFileLoader
{
public:
	wxPMHTTPFileLoader();
	~wxPMHTTPFileLoader();

	// overriden methods of wxPMFileLoader
	virtual wxPMFileLoader* Clone();
	virtual bool CanAcceptPath( const wxString& path );
	virtual bool FileExists();
	virtual bool CanWrite();

	virtual wxInputStream* GetInputStream();
	virtual wxOutputStream* GetOutputStream();

	virtual bool IsOpen();
	virtual bool Close();

	virtual int GetLocationType();
	virtual wxString GetLocationTypeStr();

	DECLARE_DYNAMIC_CLASS( wxPMHTTPFileLoader )

protected:
	wxInputStream* m_pInputStream;

};

class wxPMFTPFileLoader : public wxPMFileLoader
{
public:
	wxPMFTPFileLoader();
	~wxPMFTPFileLoader();

	// overriden methods of wxPMFileLoader
	virtual wxPMFileLoader* Clone();
	virtual bool CanAcceptPath( const wxString& path );
	virtual bool FileExists();
	virtual bool CanWrite();
	virtual wxInputStream* GetInputStream();
	virtual wxOutputStream* GetOutputStream();

	virtual bool IsOpen();
	virtual bool Close();

	virtual int GetLocationType();
	virtual wxString GetLocationTypeStr();

	// methods specfic to this loader

	virtual void SetUser( const wxString& user );
	virtual void SetPassword( const wxString& password );

	DECLARE_DYNAMIC_CLASS( wxPMFTPFileLoader )

protected:
	wxInputStream* m_pInputStream;
	wxOutputStream* m_pOutputStream;

	wxString m_User;
	wxString m_Password;
};

// TBD:: commentds...

class wxPMSerializer : public wxConfigBase
{
public:
	wxPMSerializer( wxConfigBase* pImplementingConfig, bool isLoading );
	~wxPMSerializer();

	bool IsLoading();

	// methods for serialization (featured by wxPMSerializer)

	virtual bool Exchange( const wxString& key, long& l );
	virtual bool Exchange( const wxString& key, bool& b );
	virtual bool Exchange( const wxString& key, int& i );
	virtual bool Exchange( const wxString& key, double& d );
	virtual bool Exchange( const wxString& key, wxString& s );
	virtual bool Exchange( const wxString& key, wxPoint& pos );
	virtual bool Exchange( const wxString& key, wxSize& size );
	virtual bool Exchange( const wxString& key, wxStringList& lst );

	virtual wxString IndexedKey( const wxString& key, size_t index );

	// implemented pure virtual methods of wxConfigBase
	virtual void SetPath(const wxString& strPath);
	virtual const wxString& GetPath() const;
	virtual bool GetFirstGroup(wxString& str, long& lIndex) const;
	virtual bool GetNextGroup (wxString& str, long& lIndex) const;
	virtual bool GetFirstEntry(wxString& str, long& lIndex) const;
	virtual bool GetNextEntry (wxString& str, long& lIndex) const;
	virtual size_t GetNumberOfEntries(bool bRecursive = FALSE) const;
	virtual size_t GetNumberOfGroups(bool bRecursive = FALSE) const;
	virtual bool HasGroup(const wxString& strName) const;
	virtual bool HasEntry(const wxString& strName) const;
	virtual bool Read(const wxString& key, wxString *pStr) const;
	virtual bool Read(const wxString& key, wxString *pStr, const wxString& defVal) const;
	virtual wxString Read(const wxString& key, const wxString& defVal = wxEmptyString) const;
	virtual bool Read(const wxString& key, long *pl) const;
	virtual bool Read(const wxString& key, long *pl, long defVal) const;
	virtual long Read(const wxString& strKey, long defVal) const;
	virtual bool Read(const wxString& key, int *pi) const;
	virtual bool Read(const wxString& key, int *pi, int defVal) const;
	virtual bool Read(const wxString& key, double* val) const;
	virtual bool Read(const wxString& key, double* val, double defVal) const;
	virtual bool Read(const wxString& key, bool* val) const;
	virtual bool Read(const wxString& key, bool* val, bool defVal) const;
	virtual bool Write(const wxString& key, const wxString& value);
	virtual bool Write(const wxString& key, long value);
	virtual bool Write(const wxString& key, double value);
	virtual bool Write(const wxString& key, bool value);
	virtual bool Flush(bool bCurrentOnly = FALSE);
	virtual bool RenameEntry(const wxString& oldName, const wxString& newName);
	virtual bool RenameGroup(const wxString& oldName, const wxString& newName);
	virtual bool DeleteEntry(const wxString& key, bool bDeleteGroupIfEmpty = TRUE);
	virtual bool DeleteGroup(const wxString& key);
	virtual bool DeleteAll();

protected:
	wxConfigBase* m_pImp; // all methods are delegated to implementation object
	bool		  m_IsLoading;
};

// used as global image-locator and cache

class wxPMBitmapManager : public wxObject
{
public:
	wxPMBitmapManager();
	~wxPMBitmapManager();

	virtual void SetDefaultExtension( const wxString& ext );
	virtual void SetRelativePath( const wxString& relPath );
	virtual const wxString& GetRelativePath();
	virtual const wxString& GetDefaultExtension();

	// finds bitmap by it's "logical" name, which contains
	// no relative path nor extension

	virtual wxBitmap& FindBitmap( const wxString& name );

	// finds bitmap by it's "physical" name
	virtual wxBitmap& FindBitmapByFileName( const wxString& name );

	virtual bool BitmapExist( const wxString& name );

	virtual void ClearCache(); // removes all currenty cached bitmaps

	int DetectBitmapType( const wxString& fileName );

	// weried, but may have a use, eg. for prototyping - when 
	// we don't know the name of the file or it's not yet designed/prepared

	virtual wxBitmap& GetWrongBitmap(); 

	// creates a copy of source bitmap, where the copy
	// does not share referenced data with the source

	static wxBitmap CloneBitmapCopy( const wxBitmap& src );

	// does the same as FindBitmap, only returns the not-shared 
	// copy of originally loaded bitmap
	virtual wxBitmap FindAndCopyBitmap( const wxString& name );

protected:
	wxString      m_DefaultExt;
	wxString      m_RelPath;

	// used as default result, when loading/finding fails. It's content
	// is a 16x16 area filled with black 

	wxBitmap      m_WrongBitmap; 

	PMBitmapListT m_Bitmaps;
	wxHashTable   m_BitmapHash;

};

// TBD:: comments...

class wxPMService
{
protected: /*** protected! ***/
	wxPMService();
	virtual ~wxPMService(); // bk - virtual destructor helps clue compiler not to use it
					// service should not be deleted directly calling this dtor, 
					// instead dtor of corresponding wxObject should be called:
					// eg. "delete pMySvc->GetWxObject()"

public:
	virtual bool Start();
	virtual bool Stop();

	virtual bool IsStarted();

	// should be only called by wxPMBootStrapService class
	virtual void SetIsStarted( bool isStarted );

	virtual wxPMMergableMenuChain* GetMergableMenuChain();

	virtual wxString GetDisplayName();
	virtual wxString GetDescription();

	virtual wxObject* GetWxObject() = 0;

	// analog to COM's QueryInterface(), should
	// return NULL, if interface is not supported. Version argument
	// is null if version of the interface is not important, otherwise,
	// interface is returned only when it is compatible with the requeseted
	// version of it

	virtual void* GetInterface( const char* infName, const char* version = NULL );

	// default impl. checks for GetInterface() returning not NULL

	virtual bool SupportInterface( const char* infName, const char* version = NULL );

	// overridable for serializing service's state to workplace 
	// configuration storage/file, (@see wxPMSerializer class)

	virtual bool SerializeState( wxPMSerializer& ser );

	// methods for maintaining service-to-service
	// custom data-associations (are delegated to boot-strap service
	// which actually implements the maintenance)

	virtual bool AssociateData( wxPMService& toService,
								wxObject* pData );

	virtual wxObject* GetAssociatedData( wxPMService& forService );

protected:

	bool m_IsStarted; // altered only by wxPMBootStrapService
};

/*
 * prototype of simple GUI-less service, can be
 * used for deriving own services of such type
 */

class wxPMSimpleService : public wxEvtHandler,
						  public wxPMService
{
public:
	wxPMSimpleService();
	~wxPMSimpleService();

	// methods "recommended" for derivation

	virtual bool Start();
	virtual bool Stop();

	virtual wxPMMergableMenuChain* GetMergableMenuChain();

	virtual wxObject* GetWxObject();

	virtual void* GetInterface( const char* infName, const char* version = NULL );

	DECLARE_DYNAMIC_CLASS( wxPMSimpleService )
protected:
};

/* global access-point to the single instance of wxPMBitmapManager */

void wxSetPMBitmapManager( wxPMBitmapManager* pMgr );

wxPMBitmapManager& wxGetPMBitmapManager();
wxPMBitmapManager& wxPMBmpMgr(); // shorter-synonym

/* global utility functions of PMF */

// (will be moved to pmutil.h if there will be more)

// reads the data from given stream into string fully (till the eof).

class WXDLLEXPORT wxTextInputStream;

bool wxPMReadStreamToString( wxInputStream& stm, wxString& toString );
bool wxPMReadTextStreamToString( wxInputStream& stm, wxString& toString );

// path-manipulation global helpers (FOR NOW:: primitve imps.)

wxString wxPMConcatPaths( const wxString& basePath, const wxString relPath );
wxString wxPMGetRelativePath( const wxString& basePath, const wxString& absPath );
wxString wxPMGetAbsolutePath( const wxString& basePath, const wxString& relPath );

#endif // __PM_CMN_G__