#include "WimpLib:DocView.h"
#include <stdio.h>
#include <string.h>

#include "WimpLib:mem.h"

// Constructors
void throw_View_View(View* This, ViewVPtr* VPtr, Document* pDocument)
{
	This->m_VPtr = VPtr;
	This->m_iViewNumber = 0;
	This->m_pDocument = NULL;
	This->m_csTitle = mem_allocstring(NULL);

	throw_Document_AddView(pDocument, This);
}

// Destructor
void View_VNotView(View* This)
{
	This->m_VPtr->FDestructor(This);
}

void View_NotView(View* This)
{
	if (This)
	{
		if (This->m_pDocument != NULL)
			Document_RemoveView(This->m_pDocument, This);

		mem_free(This->m_csTitle);
		This->m_csTitle = NULL;
	}
}

// Dynamic allocation
View* throw_New_View(ViewVPtr* VPtr, Document* pDocument)
{
	View* This = mem_alloc(sizeof(View));
	if (This == NULL) return NULL;

	throw_View_View(This, VPtr, pDocument);

	return This;
}

void Delete_View(View* This)
{
	if (This)
	{
		View_VNotView(This);
		mem_free(This);
	}
}

// Attributes
Document* View_GetDocument(const View* This)
{
	return This->m_pDocument;
}

const char* View_GetTitle(const View* This)
{
	return This->m_csTitle;
}

bool View_VOnUpdate(View* This, const View* pSender, int HintType, const void* pHintData)
{
	return This->m_VPtr->FOnUpdate(This, pSender, HintType, pHintData);
}

bool View_OnUpdate(View* This, const View* pSender, int HintType, const void* pHintData)
{
	IGNORE(This);
	IGNORE(pSender);
	IGNORE(HintType);
	IGNORE(pHintData);

	return false;
}

void View_VSetViewNumber(View* This, int iViewNumber)
{
	This->m_VPtr->FSetViewNumber(This, iViewNumber);
}

int View_GetViewNumber(const View* This)
{
	return This->m_iViewNumber;
}

void View_SetViewNumber(View* This, int iViewNumber)
{
	const char* pDocTitle = Document_GetPathName(This->m_pDocument);
	int         count = Document_GetViewsCount(This->m_pDocument);
	int         len = strlen(pDocTitle) + 24;
	char*       pTitle = mem_alloc(len);

	if (pTitle == NULL) return;

	This->m_iViewNumber = iViewNumber;

	if (count > 1)
	{
		snprintf(pTitle, len, "%s [%d/%d]", pDocTitle, This->m_iViewNumber, count);
	}
	else
		snprintf(pTitle, len, "%s", pDocTitle);

	if (Document_IsModified(This->m_pDocument))
		strncat(pTitle, " *", len - strlen(pTitle));

	mem_free(This->m_csTitle);
	This->m_csTitle = pTitle;
}

void View_VOnInitialUpdate(View* This)
{
	This->m_VPtr->FOnInitialUpdate(This);
}

void View_OnInitialUpdate(View* This)
{
	IGNORE(This);
}

bool View_VHasSelection(const View* This)
{
	return This->m_VPtr->FHasSelection(This);
}

bool View_HasSelection(const View* This)
{
	IGNORE(This);

	return false;
}

void View_OnCloseView(View* This)
{
	/* if no more views on the document, delete ourself
	 * not called if directly closing the document or terminating the app
	 */
	if ((Document_GetViewsCount(This->m_pDocument) == 1)
	&&  Document_GetAutoDeleteFlag(This->m_pDocument))
	{
		Document_OnCloseDocument(This->m_pDocument);
		return;
	}

	Delete_View(This);
}

void View_OnSaveDocument(View* This)
{
	Document_OnSaveDocument(This->m_pDocument);
}

void View_OnSaveDocumentAs(View* This)
{
	Document_OnSaveAs(This->m_pDocument, This, false, View_VHasSelection(This));
}

void View_OnSaveSelectionAs(View* This)
{
	if (!View_VHasSelection(This)) return;

	Document_OnSaveAs(This->m_pDocument, This, true, true);
}

bool View_VSendSelection(View* This, file_type type, sXFer_Chunk* pchunk)
{
	return This->m_VPtr->FSendSelection(This, type, pchunk);
}

bool View_SendSelection(View* This, file_type type, sXFer_Chunk* pchunk)
{
	IGNORE(This);
	IGNORE(type);
	IGNORE(pchunk);

	return false;
}
