#ifndef __DocView__H
#define __DocView__H

#include <stdbool.h>
#include "WimpLib:List.h"
#include "WimpLib:Coords.h"
#include "WimpLib:DragSend.h"
#include "WimpLib:XFer.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef List DocList;
typedef struct DocumentVPtr DocumentVPtr;
typedef struct Document Document;
typedef struct ViewVPtr ViewVPtr;
typedef struct View View;

struct Document
{
	const DocumentVPtr*    m_VPtr;
	char*            m_strPathName; // file name
	file_type        m_FileType;    // file type
	const file_type* m_ExportTypes; // file types supported for export
	List*            m_pViews;     // list of views
	unsigned int     m_Flags;
};

// Public Attributes
DocList* throw_DocList_Get(void);
void Delete_DocList(DocList*);
int DocList_Count(const DocList*);
Document* DocList_GetDocument(const DocList*, int Index);
Document* DocList_Find(const DocList*, const char* pname);
bool DocList_IsSafe(const DocList*);
void DocList_RemoveAllDocuments(DocList*);

// Public Constructors
void throw_Document_Document(Document*, const file_type* ptype, const DocumentVPtr* VPtr);
bool Document_IsKindOf(const Document*, const DocumentVPtr* VPtr);

// Public Destructor
void Document_VNotDocument(Document*);
void Document_NotDocument(Document*);

// Dynamic allocation
Document* throw_New_Document(DocumentVPtr* VPtr);
void Delete_Document(Document*);

// Public Attributes
const char* Document_GetPathName(const Document*);
void throw_Document_SetPathName(Document*, const char* pstrPathName);
file_type Document_GetFileType(const Document*);
const file_type* Document_GetExportTypes(const Document*);
void Document_SetFileType(Document*, file_type type);

bool Document_IsNew(const Document*);
bool Document_HasValidPath(const Document*);
bool Document_IsModified(const Document*);
void Document_SetModifiedFlag(Document*, bool bModified);
bool Document_GetAutoDeleteFlag(const Document*);
void Document_SetAutoDeleteFlag(Document*, bool);
void Document_SetNonFileFlag(Document*, bool);

// Public View operations
void throw_Document_AddView(Document*, View* pView);
void Document_RemoveView(Document*, View* pView);
View* Document_GetView(const Document*, int Index);
int Document_GetViewsCount(const Document*);

// Public Update Views (simple update)
void Document_UpdateAllViews(const Document*, const View* pSender, int HintType , const void* pHintData);

// Private View operations
void Document_OnChangedViewList(Document*);
void Document_UpdateViewsCount(const Document*);
void Document_SendInitialUpdate(const Document*);

// Handling of commands
// Public Command helpers
void Document_OnNewDocument(Document*);
bool Document_OnClearDocument(Document*);
bool Document_OnOpenDocument(Document*, const char* strPathName);
bool Document_OnReceiveDocument(Document*, const Msg_FileData* rcv);
bool Document_OnCloseDocument(Document*);
bool Document_OnSaveDocument(Document*);
bool Document_OnSaveAs(Document*, const View* pSender, bool bSetSelFlag, bool bAllowSelFlag);
bool Document_Send(Document*, const DragDrop_Info* pInfo, const char* leafname);
void Document_OpenDir(Document*);

// Public Commands implementation
void Document_ClearDocument(Document*);
void Document_CloseDocument(Document*);

// Private Commands implementation
bool Document_SaveIfModified(Document*);
bool Document_DoFileSave(Document*, const char* pstrPathName);
void Document_OnSaveIsSafe(Document*, const char* filename);

// Public Destructor
typedef void (*Document_FNotDocument)(Document*);

// Implementation overridables
// Special notifications
#include "DCSEnum.h"
typedef enum {CAS_Cancel, CAS_All, CAS_Selection} CAS;
typedef DCS_Enum (*Document_FAskDiscardCancelSave)(const Document*);
typedef void (*Document_FSaveAs)(Document*, const View* pSender, bool bSetSelFlag, bool bAllowSelFlag);

// Implementation
typedef void (*Document_FClearContents)(Document*); // delete doc items etc
typedef const _kernel_oserror* (*Document_FOpenDocument)(Document*, XFer* xfer, file_type type, const ScreenPos* pInfo);
typedef bool (*Document_FSendDocument)(Document*, file_type type, sXFer_Chunk* pchunk);

struct DocumentVPtr
{
	Document_FNotDocument           FDestructor;
	Document_FAskDiscardCancelSave  FAskDCS;
	Document_FSaveAs                FSaveAs;
	Document_FClearContents         FClearContents;
	Document_FOpenDocument          FOpenDocument;
	Document_FSendDocument          FSendDocument;
};

struct View
{
	ViewVPtr*  m_VPtr;
	Document*  m_pDocument;
	int         m_iViewNumber;
	char*       m_csTitle;
};

// Public Constructors
void throw_View_View(View*, ViewVPtr* VPtr, Document* pDocument);

// Public Destructor
void View_VNotView(View*);
void View_NotView(View*);

// Dynamic allocation
View* throw_New_View(ViewVPtr* VPtr, Document* pDocument);
void Delete_View(View*);

// Public Attributes
Document* View_GetDocument(const View*);
const char* View_GetTitle(const View*);
bool View_VOnUpdate(View*, const View* pSender, int HintType, const void* pHintData);
bool View_OnUpdate(View*, const View* pSender, int HintType, const void* pHintData);
int View_GetViewNumber(const View*);
void View_VSetViewNumber(View*, int iViewNumber);
void View_SetViewNumber(View*, int iViewNumber);
void View_VOnInitialUpdate(View*);
void View_OnInitialUpdate(View*); // called first time after construct
bool View_VHasSelection(const View*);
bool View_HasSelection(const View*);

// Public Handling of commands
void View_OnCloseView(View*);
void View_OnSaveDocument(View*);
void View_OnSaveDocumentAs(View*);
void View_OnSaveSelectionAs(View*);

// Protected Handling of commands
bool View_VSendSelection(View*, file_type type, sXFer_Chunk* pchunk);
bool View_SendSelection(View*, file_type type, sXFer_Chunk* pchunk);

typedef bool (*View_FOnUpdate)(View*, const View* pSender, int HintType, const void* pHintData);
typedef void (*View_FSetViewNumber)(View*, int iViewNumber);
typedef void (*View_FOnInitialUpdate)(View*);
typedef bool (*View_FHasSelection)(const View*);
typedef bool (*View_FSendSelection)(View*, file_type type, sXFer_Chunk* pchunk);
typedef void (*View_FNotView)(View*);

struct ViewVPtr
{
	View_FOnUpdate        FOnUpdate;
	View_FSetViewNumber   FSetViewNumber;
	View_FOnInitialUpdate FOnInitialUpdate;
	View_FHasSelection    FHasSelection;
	View_FSendSelection   FSendSelection;
	View_FNotView         FDestructor;
};

#ifdef __cplusplus
}
#endif

#endif
