/******************************************************************************
 GMessageHeaderList.cc

	BASE CLASS = public JPtrArray <GMessageHeader>

	Copyright © 1997 by Glenn W. Bach.  All rights reserved.
	
	Base code generated by Codemill v0.1.0

 *****************************************************************************/

//Class Header
#include <GMessageHeaderList.h>
#include <GMScanner.h>
#include <GPrefsMgr.h>
#include <GMGlobals.h>

#include <JProgressDisplay.h>
#include <JString.h>
#include <JUserNotification.h>
#include <JCreateProgressDisplay.h>
#include <JRegex.h>

#include <jXGlobals.h>

#include <jDirUtil.h>
#include <jFileUtil.h>
#include <jProcessUtil.h>
#include <jStreamUtil.h>

#include <fstream.h>
#include <iostream.h>
#include <jAssert.h>


/******************************************************************************
 Static OkToCreate function

 *****************************************************************************/

static const JRegex fromRegex("^From[[:space:]]+.*.{3}[[:space:]]+.{3}[[:space:]]+[[:digit:]]+[[:space:]]+([[:digit:]]+:)+[[:digit:]]+[[:space:]]+(...[[:space:]])?[[:digit:]]{4}");

JBoolean 
GMessageHeaderList::OkToCreate
	(
	const JString& 			mailfile
	)
{
	if (!JFileExists(mailfile))
		{
		JString smbox 	= GGetPrefsMgr()->GetDefaultInbox();
		if (mailfile == smbox)
			{
			return kTrue;
			}
		JString notice 	= "The file \"" + mailfile + "\" does not exist.";
		JGetUserNotification()->ReportError(notice);
		return kFalse;
		}
	if (!JFileReadable(mailfile))
		{
		JString notice = "The file \"" + mailfile + "\" is not readable.";
		JGetUserNotification()->ReportError(notice);
		return kFalse;
		}
	mode_t perms;
	JError err = JGetPermissions(mailfile, &perms);
	if (!err.OK())
		{
		perms = 0600;
		}
	ifstream is(mailfile, ios::in, perms);
	is >> ws;
	JString line1 = JReadLine(is);
	is.close();
	JBoolean matched;
	JArray<JIndexRange>* subList = new JArray<JIndexRange>;
	assert(subList != NULL);
//	err = regex.SetPattern("^From[[:space:]]+.*.{3}[[:space:]]+.{3}[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+:[[:digit:]]+:[[:digit:]]+[[:space:]]+[[:digit:]]{4}");
//	err = regex.SetPattern("^From[[:space:]]+.*.{3}[[:space:]]+.{3}[[:space:]]+[[:digit:]]+[[:space:]]+([[:digit:]]+:)+[[:digit:]]+[[:space:]]+(...[[:space:]])?[[:digit:]]{4}");
//	assert(err.OK());
	matched = fromRegex.Match(line1, subList);
	delete subList;
	if (matched || line1 == "")
		{
		return kTrue;
		}
	else
		{
		JString notice = "The file \"" + mailfile + "\" is not a mail file.";
		JGetUserNotification()->ReportError(notice);
		return kFalse;
		}
	return kFalse;
}

/******************************************************************************
 Static Create function

 *****************************************************************************/

JBoolean 
GMessageHeaderList::Create
	(
	const JString& 			mailfile, 
	GMessageHeaderList** 	list,
	JProgressDisplay* 		pg
	)
{
	JBoolean ok = OkToCreate(mailfile);
	if (ok)
		{
		JString bakfile = mailfile + "~";
		if (!JFileExists(bakfile))
			{
			JString cmd = "cp \"" + mailfile + "\" \"" + bakfile + "\"";
//			JExecute(cmd, NULL);
			}
		*list = new GMessageHeaderList(mailfile, pg);
		assert(*list != NULL);
		}
	else
		{
		*list = NULL;
		}
	return ok;
}

/******************************************************************************
 Constructor

 *****************************************************************************/

GMessageHeaderList::GMessageHeaderList
	(
	const JString& 		mailfile,
	JProgressDisplay* 	pg
	)
	:
	JPtrArray<GMessageHeader>()
{
	JSize size;
	const JError sizeErr = JGetFileLength(mailfile, &size);
//	assert(sizeErr.OK());
	JSize pgcount = 0;
	pg->FixedLengthProcessBeginning(size, "Reading mail file.", kFalse, kFalse);
	itsMailFile = new JString(mailfile);
	itsIsWritable = JFileWritable(mailfile);
	mode_t perms;
	JError err = JGetPermissions(mailfile, &perms);
	if (!err.OK())
		{
		perms = 0600;
		}
	ifstream is(mailfile, ios::in, perms);
	GMScanner scanner(&is);
	JIndex token;
	GMessageHeader* header = NULL;
	while ((token = scanner.yylex()) != 0)
		{
		if (token == kHeaderStart)
			{
			if (header != NULL)
				{
				JSize current = scanner.GetCurrentHeaderStart();
				header->SetMessageEnd(current);
//				current = current * 20/size;
//				while ((pgcount <= current) && (pgcount <= 20))
				if (current < size)
					{
//					cout << pgcount << endl;
					pg->IncrementProgress(current - pg->GetCurrentStepCount());
//					pgcount++;
					}
				}
			header = new GMessageHeader();
			assert(header != NULL);
			Append(header);
			header->SetHeader(scanner.YYText());
			header->SetHeaderStart(scanner.GetCurrentHeaderStart());
			}
		else if (token == kHeaderEnd)
			{
			assert(header != NULL);
			header->SetHeaderEnd(scanner.GetCurrentPosition());
			}
		else if (token == kFrom)
			{
			assert(header != NULL);
			header->SetFrom(scanner.YYText());
			}
		else if (token == kTo)
			{
			assert(header != NULL);
			header->SetTo(scanner.YYText());
			}
		else if (token == kSubject)
			{
			assert(header != NULL);
			header->SetSubject(scanner.YYText());
			}
		else if (token == kDate)
			{
			assert(header != NULL);
			header->SetDate(scanner.YYText());
			}
		else if (token == kCC)
			{
			assert(header != NULL);
			header->SetCC(scanner.YYText());
			}
		else if (token == kReplyTo)
			{
			assert(header != NULL);
			header->SetReplyTo(scanner.YYText());
			}
		else if (token == kStatus)
			{
			assert(header != NULL);
			JString status(scanner.YYText());
			if (status.Contains("R") && 
				(header->GetMessageStatus() == GMessageHeader::kNew))
				{
				header->SetMessageStatus(GMessageHeader::kRead);
				}
			}
		}
	if (header != NULL)
		{
		JSize current = scanner.GetCurrentPosition();
		header->SetMessageEnd(current);
//		current = current * 20/size;
//		while (pgcount <= current)
//			{
//			cout << "Last: " << pgcount << endl;
//			pg->IncrementProgress();
//			pgcount++;
//			}
		}
	is.close();
	pg->ProcessFinished();
}

/******************************************************************************
 Destructor

 *****************************************************************************/

GMessageHeaderList::~GMessageHeaderList()
{
	RemoveAll();
	delete itsMailFile;
}
