//	CFinderWindowHeader.c

#include "ADFS_Commands.h"
#include "CAppearance.h"
#include "DeviceManager.h"
#include "Utils.h"
#include "ADFS_Menus.h"
#include "ADFS_Prefs.h"
#include "CFinderWindowHeader.h"

OSErr		CFinderWindowHeader::IFinderWindowHeader(CFinderWindow *window)
{
	OSErr		err;
	
	//	maybe allocate an offscreen?
	err = InitStats();
	
	i_window		= window;
	i_nameExtra		= 0;
	i_tempString[0]	= 0;
	i_showStats		= TRUE;
	
	i_viewAs		= (ADFS_ViewAsType)(**gPrefsH).windowPrefs[kDTWindIndex].viewAs;
	i_arrangeBy		= (ADFS_StatType)(**gPrefsH).windowPrefs[kDTWindIndex].arrangeBy;
	i_reversedB		= (**gPrefsH).windowPrefs[kDTWindIndex].reversedB;

	return err;
}

void		CFinderWindowHeader::Dispose(void)
{
	delete this;
}

void		CFinderWindowHeader::Flush(void)
{
	i_window->Flush();
}

ADFS_StatItem			gStats[ADFS_Stat_NUMTYPES] = {
	{	"\p", 				0,		0,		ADFS_StatNoBorder,	ADFS_Justify_NONE	},  //	NONE
	{	"\p",				17,		17,		ADFS_StatNoBorder,	ADFS_Justify_NONE	},  //	TWIRLY
	{	"\p#", 				23,		23,		ADFS_StatBorder,	ADFS_Justify_RIGHT	},  //	INDEX
	{	"\p",				19,		19,		ADFS_StatNoBorder,	ADFS_Justify_NONE	},  //	ICON
	{	"\pName",			80,		100,	ADFS_StatBorder,	ADFS_Justify_LEFT	}, 
	{	"\pSize", 			38,		38,		ADFS_StatBorder,	ADFS_Justify_RIGHT	}, 	//	physical
	{	"\pUsed", 			38,		38,		ADFS_StatBorder,	ADFS_Justify_RIGHT	}, 	//	logical
	{	"\pKind", 			50,		100,	ADFS_StatBorder,	ADFS_Justify_LEFT	}, 
	{	"\pCreation Date", 	75, 	154, 	ADFS_StatBorder,	ADFS_Justify_LEFT	}, 
	{	"\pLast Modified", 	75, 	154, 	ADFS_StatBorder,	ADFS_Justify_LEFT	}, 
	{	"\pLock", 			40, 	40, 	ADFS_StatNoBorder,	ADFS_Justify_LEFT	}, 
};

OSErr		CFinderWindowHeader::InitStats(void)
{
	ADFS_StatType			statType;
	ADFS_DiskInfoType		infoType;

	ADFS_HeaderStr			gDiskInfos[ADFS_DiskInfo_NUMTYPES] = {
		"\p",
		"\p items",
		"\p in disk",
		"\p available"
	};
	
	ADFS_Stat_FOR_EACH(statType) {
		i_stats[statType] = gStats[statType];
		i_stats[statType].width = (**gPrefsH).windowPrefs[kDTWindIndex].columnWidths[statType];
		if (i_stats[statType].width < i_stats[statType].minWidth) {
			i_stats[statType].width < i_stats[statType].minWidth;
		}
	}

	ADFS_DiskInfo_FOR_EACH(infoType) {
		CopyString(gDiskInfos[infoType], i_diskInfos[infoType]);
	}
	
	return noErr;
}

void	CFinderWindowHeader::SetNameExtra(short nameExtra)
{
	i_nameExtra = nameExtra;
}

void	CFinderWindowHeader::ShowStats(Boolean showStats)
{
	i_showStats = showStats;
}

ADFS_ViewAsType		ADFS_CommandToViewAs(ulong command)
{
	ADFS_ViewAsType	statType;
	
	switch (command) {

		case cmdViewAsIcons: {
			statType = ADFS_ViewAs_ICONS;
			break;
		}
		
		default:
		case cmdViewAsList: {
			statType = ADFS_ViewAs_LIST;
			break;
		}

//		case cmdViewAsColumns: {
//			statType = ADFS_ViewAs_COLUMNS;
//			break;
//		}
	}
	
	return statType;
}

ulong			ADFS_ViewAsToCommand(ADFS_ViewAsType statType)
{
	ulong	command;
	
	switch (statType) {
	
		case ADFS_ViewAs_ICONS: {
			command = cmdViewAsIcons;
			break;
		}

		default:
		case ADFS_ViewAs_LIST: {
			command = cmdViewAsList;
			break;
		}

//		case ADFS_ViewAs_COLUMNS: {
//			command = cmdViewAsColumns;
//			break;
//		}
	}
	
	return command;
}

ADFS_StatType	ADFS_CommandToStat(ulong command)
{
	ADFS_StatType	statType;
	
	switch (command) {

		case cmdArrangeByIndex: {
			statType = ADFS_Stat_INDEX;
			break;
		}
		
		default:
		case cmdArrangeByName: {
			statType = ADFS_Stat_NAME;
			break;
		}

		case cmdArrangeByModDate: {
			statType = ADFS_Stat_MOD_DATE;
			break;
		}

		case cmdArrangeByCreDate: {
			statType = ADFS_Stat_CRE_DATE;
			break;
		}

		case cmdArrangeBySize: {
			statType = ADFS_Stat_SIZE;
			break;
		}

		case cmdArrangeByUsed: {
			statType = ADFS_Stat_USED;
			break;
		}

		case cmdArrangeByKind: {
			statType = ADFS_Stat_KIND;
			break;
		}
	}
	
	return statType;
}

ulong			ADFS_StatToCommand(ADFS_StatType statType)
{
	ulong	command;
	
	switch (statType) {
	
		case ADFS_Stat_TWIRLIE: {
			command = cmdArrangeByName;
			break;
		}

		case ADFS_Stat_INDEX: {
			command = cmdArrangeByIndex;
			break;
		}

		default:
		case ADFS_Stat_NAME: {
			command = cmdArrangeByName;
			break;
		}

		case ADFS_Stat_SIZE: {
			command = cmdArrangeBySize;
			break;
		}

		case ADFS_Stat_USED: {
			command = cmdArrangeByUsed;
			break;
		}

		case ADFS_Stat_KIND: {
			command = cmdArrangeByKind;
			break;
		}

		case ADFS_Stat_CRE_DATE: {
			command = cmdArrangeByCreDate;
			break;
		}

		case ADFS_Stat_MOD_DATE: {
			command = cmdArrangeByModDate;
			break;
		}

		case ADFS_Stat_LOCK: {
			command = cmdArrangeByName;
			break;
		}
	}
	
	return command;
}

void	CFinderWindowHeader::HitTest(
	Point			thePoint, 
	WindowRectType	*pane, 
	short			*subPane, 
	Rect			*hitRect)
{
	ADFS_StatType		statType;
	Rect				theRect = i_window->GetWindowRect(WindowRect_HEADER_STAT_INFO);

	ADFS_Stat_FOR_EACH(statType) {
		GetStatSize(statType, &theRect.left, &theRect.right);
		if (PtInRect(thePoint, &theRect)) {
			*hitRect = theRect;
			*subPane = statType;
			*pane = WindowRect_HEADER_STAT_INFO;
		} else {
			theRect.left = theRect.right;
			theRect.right += GetStatBorder(statType);
			if (PtInRect(thePoint, &theRect)) {
				*hitRect = theRect;
				*subPane = statType | 0x80;
				*pane = WindowRect_HEADER_STAT_INFO;
			}
		}
	}
}

void	CFinderWindowHeader::DoClick(
	Point			thePoint, 
	WindowRectType	pane, 
	short			subPane, 
	const Rect		*hitRect)
{
	if ((subPane & 0x80) != 0) {
		Point	newPoint;
		short	oldWidth;
		
		subPane &= 0x7F;
		
		oldWidth = i_stats[subPane].width;

		do {
			GetMouse(&newPoint);
			i_stats[subPane].width += newPoint.h - thePoint.h;
			
			if (i_stats[subPane].width < i_stats[subPane].minWidth) {
				i_stats[subPane].width = i_stats[subPane].minWidth;
			} else {
				thePoint.h = newPoint.h;
			}
			
			if (i_stats[subPane].width != oldWidth) {
				i_window->UnPrepare();
				Draw();
				Flush();
				i_window->Prepare();
				oldWidth = i_stats[subPane].width;
			}

		} while (StillDown_Loop());

		(**gPrefsH).windowPrefs[kDTWindIndex].columnWidths[subPane] 
			= i_stats[subPane].width;
		SavePrefs();
		
		i_window->InvalWindow(WindowRect_INTERIOR);
	} else {
		if (subPane != ADFS_Stat_TWIRLIE) {
			DoCommand(ADFS_StatToCommand((ADFS_StatType)subPane));
		}
	}
}

/*
#define	menuView                 0x0084
#define	cmdViewAsIcons           0x00840001
#define	cmdShowLargeIcons        0x00840002
#define	cmdViewAsList            0x00840003
#define	cmdCleanUpWindow         0x00840005
#define	cmdArrangeSub            0x00840006
#define	cmdSetIndexOrder         0x00840008

#define	subArrange               0x00CB
#define	cmdArrangeByIndex        0x00CB0001
#define	cmdArrangeByName         0x00CB0002
#define	cmdArrangeBySize         0x00CB0003
#define	cmdArrangeByUsed         0x00CB0004
#define	cmdArrangeByCreDate      0x00CB0005
#define	cmdArrangeByModDate      0x00CB0006
#define	cmdArrangeByKind         0x00CB0007
#define	cmdArrangeByLock         0x00CB0008
*/

Boolean		CFinderWindowHeader::DoCommand(long command)
{
	Boolean		handled = FALSE;
	
	if (!handled) switch (CommandMenu(command)) {
		
		case subArrange: {
			ADFS_StatType		arrangeBy = ADFS_CommandToStat(command);
			
			handled		= TRUE;
			i_viewAs	= ADFS_ViewAs_LIST;
			
			if (i_arrangeBy == arrangeBy) {
				i_reversedB = !i_reversedB;
			} else {
				i_arrangeBy = arrangeBy;
			}
			break;
		}
		
		case menuView: {
			handled		= TRUE;
			i_viewAs	= ADFS_CommandToViewAs(command);
			break;
		}
	}

	if (handled) {
		(**gPrefsH).windowPrefs[kDTWindIndex].viewAs	= i_viewAs;
		(**gPrefsH).windowPrefs[kDTWindIndex].arrangeBy = i_arrangeBy;
		(**gPrefsH).windowPrefs[kDTWindIndex].reversedB = i_reversedB;
		SavePrefs();

		i_window->InvalWindow(WindowRect_HEADER);
		i_window->UpdateSort();
	}
		
	return handled;
}

extern	Boolean		g_black_and_whiteB;

void	CFinderWindowHeader::Draw(void)
{
	Rect				theRect;
	ADFS_DiskInfoType	infoType;
	ADFS_StatType		statType;
	unsigned char		infoStr[256];
	short				stringWidth;
	
	theRect = i_window->GetWindowRect(WindowRect_HEADER_DISK_INFO);
	APR_BevelFrame(&theRect);
	
	ADFS_DiskInfo_FOR_EACH(infoType) {
	}
	
	CopyString(c2p("0 items, 0 K used, 0 K available"), infoStr);
	stringWidth = StringWidth(infoStr);
	MoveTo(((theRect.right - theRect.left) >> 1) - (stringWidth >> 1), theRect.bottom - 7);

	Boolean		wasWB = g_black_and_whiteB;
	
	g_black_and_whiteB = RectDepth(&theRect, kMinDepth) < 8;
	APR_SetBackColor(APR_Color_VERY_LIGHT);
	g_black_and_whiteB = wasWB;

	DrawString(infoStr);
	APR_SetBackColor(APR_Color_WHITE);

	theRect = i_window->GetWindowRect(WindowRect_HEADER_STAT_INFO);
	ADFS_Stat_FOR_EACH(statType) {
		Boolean		pressedB = i_arrangeBy == statType;
		
		GetStatSize(statType, &theRect.left, &theRect.right);
		theRect.right += GetStatBorder(statType);
		APR_BevelButton(&theRect, i_stats[statType].name, pressedB);
		
		//	draw the "reverse" triangle
		if (pressedB) {
			Rect	triangleRect = theRect;
			
			triangleRect.right -= GetStatBorder(statType);
			triangleRect.left = triangleRect.right - 8;
			InsetRect(&triangleRect, 0, 5);
			triangleRect.top++;
			
			DrawTriangle(
				(QD_TriangleType)(QD_Triangle_UP + i_reversedB), 
				&triangleRect);
		}
		
		//	draw the little resizer thing ("border")  why is it called border?
		if (GetStatBorder(statType)) {
			theRect.left = theRect.right - GetStatBorder(statType);
			InsetRect(&theRect, 3, 3);
			APR_BevelFrame(&theRect);
			InsetRect(&theRect, -3, -3);
		}
	}
	
	GetStatSize(ADFS_Stat_NUMTYPES, &theRect.left, &theRect.right);
	APR_BevelFrame(&theRect);	
}

ADFS_JustifyType	CFinderWindowHeader::GetStatJustify(ADFS_StatType statType)
{
	return i_stats[statType].justify;
}

short	CFinderWindowHeader::GetStatBorder(ADFS_StatType statType)
{
	return i_stats[statType].border;
}

void	CFinderWindowHeader::GetStatSize(ADFS_StatType statType, short *left, short *right)
{
	(*left)		= 0;
	(*right)	= i_stats[statType].width;
	
	if (statType >= ADFS_Stat_NAME) {
		
		(*right) += i_nameExtra;
		
		if (statType > ADFS_Stat_NAME) {
			(*left) += i_nameExtra;
		}
	}
	
	statType = ADFS_Stat_DEC(statType);

	ADFS_Stat_FOR_REVERSE(statType) {
		(*left) += i_stats[statType].width + i_stats[statType].border;
	}

	(*right) += (*left);
}
