/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 1, or (at your option)
** any later version.

** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.

** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
 * Author : Alexandre Parenteau <aubonbeurre@hotmail.com> --- December 1997
 */

// GraphDoc.cpp : implementation of the CGraphDoc class
//

#include "stdafx.h"

#include <direct.h>
#include <sys/stat.h>

#include "Wincvs.h"

#include "GraphDoc.h"
#include "CvsLog.h"
#include "WinCvsView.h"
#include "GraphView.h"
#include "CvsEntries.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CGraphDoc

IMPLEMENT_DYNCREATE(CGraphDoc, CDocument)

BEGIN_MESSAGE_MAP(CGraphDoc, CDocument)
	//{{AFX_MSG_MAP(CGraphDoc)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
	ON_COMMAND(ID_FILE_SEND_MAIL, OnFileSendMail)
	ON_UPDATE_COMMAND_UI(ID_FILE_SEND_MAIL, OnUpdateFileSendMail)
END_MESSAGE_MAP()

BEGIN_DISPATCH_MAP(CGraphDoc, CDocument)
	//{{AFX_DISPATCH_MAP(CGraphDoc)
	DISP_FUNCTION(CGraphDoc, "NumNodes", NumNodes, VT_I4, VTS_NONE)
	//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()

// Note: we add support for IID_ITest to support typesafe binding
//  from VBA.  This IID must match the GUID that is attached to the 
//  dispinterface in the .ODL file.

// {09F456B5-0018-11D2-BCAA-000000000000}
static const IID IID_ITest =
{ 0x9f456b5, 0x18, 0x11d2, { 0xbc, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };

BEGIN_INTERFACE_MAP(CGraphDoc, CDocument)
	INTERFACE_PART(CGraphDoc, IID_ITest, Dispatch)
END_INTERFACE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGraphDoc construction/destruction

CGraphDoc::CGraphDoc()
{
	EnableAutomation();

	AfxOleLockApp();

	fNode = 0L;
	fData = 0L;
}

CGraphDoc::~CGraphDoc()
{
	AfxOleUnlockApp();

	PrepareNew();
}

void CGraphDoc::PrepareNew(void)
{
	if(fNode != 0L)
	{
		delete fNode;
		fNode = 0L;
	}
	if(fData != 0L)
	{
		fData->UnRef();
		fData = 0L;
	}
	fDir.Empty();
	fName.Empty();
}

BOOL CGraphDoc::OnNewDocument()
{
	PrepareNew();

	if (!CDocument::OnNewDocument())
		return FALSE;

	return TRUE;
}

static void NormalizeFn(const char* folder, const char* fn, char* dir, char* name)
{
	char buffer[_MAX_PATH];
	char dirBuffer[_MAX_PATH];
	char nameBuffer[_MAX_PATH];
	char drive[_MAX_PATH];
	char ext[_MAX_EXT];
	_makepath(buffer, NULL, folder, fn, NULL);
	_splitpath(buffer, drive, dirBuffer, nameBuffer, ext);
	_makepath(dir, drive, dirBuffer, NULL, NULL);
	_makepath(name, NULL, NULL, nameBuffer, ext);
}

void CGraphDoc::SetNode(CLogNode *node, const char *folder)
{
	PrepareNew();

	// normalize folder/fname since the latter can be a path relative to folder
	const char *fn = (**(CLogNodeHeader *)node).WorkingFile();
	char dir[_MAX_PATH];
	char name[_MAX_PATH];
	NormalizeFn(folder, fn, dir, name);

	fNode = node;
	fDir = dir;

	// get the CVS/Entries infos for this file
	CSortList<ENTNODE> entries(200, ENTNODE::Compare);
	if(!Entries_Open (entries, dir))
	{
		cvs_err("Warning : Error while accessing the CVS folder in '%s'\n", dir);
	}
	else
	{
		if(node->GetType() != kNodeHeader)
		{
			cvs_err("Warning : Top node is not a RCS file description !\n");
		}
		else
		{
			struct stat sb;
			if (stat(fn, &sb) == -1)	//JK - used to be "name", fix for the flat mode
			{
				cvs_err("Warning : Unknown file '%s'\n", name);
			}
			else
			{
				fData = Entries_SetVisited(dir, entries, name, sb, false);
				fData->Ref();
				fName = name;
			}
		}
	}

	// create the graph and redraw
	CGraphView *view = GetTreeView();
	if(view != 0L)
	{
		view->CalcImageSize();
		view->Invalidate();
		SetTitle(fName);
	}
}


/////////////////////////////////////////////////////////////////////////////
// CGraphDoc serialization

void CGraphDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

CGraphView *CGraphDoc::GetTreeView(void)
{
	POSITION posv = GetFirstViewPosition();
	CView* view;
	while(posv != NULL)
	{
		view = GetNextView(posv);
		if(view->IsKindOf(RUNTIME_CLASS(CGraphView)))
			return (CGraphView *)view;
	}
	return NULL;
}

/////////////////////////////////////////////////////////////////////////////
// CGraphDoc diagnostics

#ifdef _DEBUG
void CGraphDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CGraphDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CGraphDoc commands

long CGraphDoc::NumNodes() 
{
	return 0;
}
