//
// Overview.m
// Copyright (c) 1988, 1989, 1990 by Jiro Nakamura 
// All rights reserved
//
// Handles the Overview window for Cassandra
//
//	by Jiro Nakamura (ac6y@vax5.cit.cornell.edu)
//
// RCS Information
// Revision Number->	$Revision: 3.6 $
// Last Revised->	$Date: 90/12/03 01:56:28 $
//
static char rcsid[] = "$Id: Overview.m,v 3.6 90/12/03 01:56:28 jiro Exp Locker: jiro $";

#import <appkit/Form.h>
#import <appkit/ScrollView.h>
#import <appkit/Window.h>
#import <appkit/Bitmap.h>	// for Miniworld bitmap
#import <appkit/Panel.h>       	// for NXRunAlertPanel 
#import <appkit/Application.h> 	// for NX_MODALRESPTHRESHOLD 
#import <appkit/Font.h>		// for Font

#import <sys/time.h>		
#import <sys/file.h>
#import <libc.h>
#import <strings.h>

#import "Overview.h"
#import "Event.h"
#import "Global.h"
#import "misc.h"
#import "calendar.h"

// The font point size of the months
#define FONTNAME_MONTHS	"Courier"
#define FONTSIZE_MONTHS	12.0

// The minimum dimensions of the overview window
#define MIN_WIDTH			500.0
#define MIN_HEIGHT			280.0

// This function's predeclaration
void showCalendar(  int month, int year, id cal);

@implementation Overview
+ new
{
	char	dumbChar[5];
	
	// dumb references to some static constants, just
	// to avoid warning messages from the compiler (Garance)
	dumbChar[0] = rcsid[0];		// dumb de dumb

	#ifdef DEBUG
		fprintf(stderr,"Overview being created.\n");
	#endif
  	
	self = [super new];
	[self	setDelegate:self];
	return self;
}

- free
{
	[eventText free];
	[super free];
	return nil;
}

- open: sender
{
	static alreadyInited = FALSE;

	if( !alreadyInited)
		{
		alreadyInited = TRUE;

		[self placeWindow: [global overviewFrame]];
		
		showSeconds = [global showSeconds];
		lowPriority  = [global lowPriority];
		militaryTime = [global militaryTime];

		[lastMonthText setSelectable:NO];
		[thisMonthText setSelectable:NO];
		[nextMonthText setSelectable:NO];

		[thisMonthText	setOpaque:	YES];
		[lastMonthText	setOpaque:	YES];	
		[nextMonthText	setOpaque:	YES];
	
		[thisMonthText	setMonoFont:	NO];
		[lastMonthText	setMonoFont:	NO];	
		[nextMonthText	setMonoFont:	NO];

		[thisMonthText	setBackgroundGray:	NX_LTGRAY];
		[lastMonthText	setBackgroundGray:	NX_LTGRAY];
		[nextMonthText	setBackgroundGray:	NX_LTGRAY];

		[thisMonthText	setTextGray:	NX_BLACK];
		[lastMonthText	setTextGray:	NX_DKGRAY];
		[nextMonthText	setTextGray:	NX_DKGRAY];
		
		[self windowDidUpdate: self];
		[self setMiniwindowIcon: OVERVIEWICON];
		
		priorityCutOff = [global lowPriority];
		viewPopUp = 		[PopUpList new];
		[viewPopUp	addItem:	"View All"];
		[viewPopUp	addItem:	"View Mid~High"];
		[viewPopUp	addItem:	"View Only High"];
		[[viewPopUp itemList] selectCellAt:1:0];
		NXAttachPopUpList(viewPopUpButton, viewPopUp);
		}
		
	[self makeKeyAndOrderFront: sender];
	[self	timeUpdate: self];
	
	[self monthRedraw];
	
	return self;
}
		
- close
{
	[global	saveThisWindowPosition: DEFAULTOVERVIEWFRAME: self];
	[super close];
	return self;
}

- printPSCode: sender
{
	[eventText printPSCode: self];
	return self;
}

- defaultsDidChange: sender
{
	#ifdef DEBUG
		fprintf(stderr,"Defaults changed.... Overview compensating\n");
	#endif

	showSeconds = [global showSeconds];
	
	if( (militaryTime != [global militaryTime]) || 
	    (lowPriority  != [global lowPriority]))
		{
		militaryTime = [global militaryTime];
		lowPriority  = [global lowPriority];
		[self queueDidChange: self];
		}
	return self;
}

- queueDidChange : sender
{
	#ifdef DEBUG
		fprintf(stderr,"Queue changed.... Overview compensating\n");
	#endif

	[self listUpdate:self];
	return self;
}

- windowDidUpdate: sender
{
	#ifdef DEBUG
		fprintf(stderr,"Yup, window updated.\n\n");
	#endif

	eventText = [eventScroll docView];
	[eventText setFont: 
			[Font newFont: 	[global fontName]
					 size:	[global fontSize]]];
	[eventText setEditable: FALSE];
	
	monthNow 	= timeNow()->tm_mon;
	yearNow 	= timeNow()->tm_year;
	showCalendar( monthNow, 	yearNow, thisMonthText);
	showCalendar( monthNow+1, 	yearNow, nextMonthText);
	showCalendar( monthNow-1, 	yearNow, lastMonthText);
	
	[self listUpdate:self];
	return self;
}

- windowWillResize: (id) sender toSize: (NXSize *) size
{
	#ifdef DEBUG
		fprintf(stderr,"Window would have resized to %f x %f.\n", size->width, size->height);
	#endif
	
	if( size->width < MIN_WIDTH)
		size->width = MIN_WIDTH;
	if( size->height < MIN_HEIGHT)
		size->height = MIN_HEIGHT;
		
	#ifdef DEBUG
		fprintf(stderr,"Window will resize to %f x %f.\n", size->width, size->height);
	#endif
	return self;
}

// This method updates the event queue as displayed by the
// Overview
- listUpdate: sender
{
	NXStream *output; 
	Event *ev;
	int  today, lastday, temp;
	char annvTemp[30];
	static char *  annv[5] = {"???","days","weeks","months","years"};
	static char *  annv2[5] = {"???","Daily","Weekly","Monthly","Yearly"};


	// We want to read the eventFile pointed to by global 
	ev = [Event newAt:[global eventFile]];

	// We need a temporary memory stream to store the queue.
	if( (output = NXOpenMemory( NULL, 0, NX_READWRITE)) == NULL)
		{
		fprintf(stderr,"%s: Couldn't open memory stream for "
			"Overview queue scrollview. FATAL ERRROR.\n",
			PROGNAME);
		exit(1) ;
		}
				
	[ev firstEvent];	
	today = [ev mday];
	
	NXPrintf(output, "{\\rtf0\\ansi{\\fonttbl\\f0\\fmodern "
				"%s;}\\fs%.0f\n",
				[global fontName], [global fontSize] * 2);

	/* Print all events for today regardless of priority, */
	/* today being the */
	/* first day in the event queue */
	
	if( [ev present] == 0)	/* If it is an empty queue */
		NXPrintf(output, "{\\f0 "
				"----      Empty Event Queue      ----"
				"\\par}\n");
	else	
		NXPrintf(output,	"{\\f0\\b %s\\par}\n",
			ascMyDate([ev time]));
		

	while ( [ev present] != 0 && [ev mday] == today)
		{
		if( [ev anniversary]>0)	/*If there is an anniversary event */
			{
			if( [ev anniversary] % 100 > 1)
				sprintf(annvTemp, "(Every %d %s)", 
					[ev anniversary] % 100, 
					annv[ ( [ev anniversary] / 100) ]);
			else
				sprintf(annvTemp, "(%s)", 
					annv2[ ( [ev anniversary] / 100) ]);
			}
		else
			strcpy(annvTemp , "");
			
		if( [ev priority] > [global highPriority])
			NXPrintf(output, "{\\f0\\b ");
		else
			NXPrintf(output, "{\\f0 ");

		if( [global militaryTime])
			NXPrintf(output, "  %3d]  %2d:%02d  \t%s"
					"\t%s\\par}", 
				[ev present],  
				[ev hour], [ev min],
				[ev message], annvTemp);
		else
			{
			temp = [ev hour];
			
			if( temp > 12 )
				temp -= 12;
			if( temp == 0 )
				temp = 12;
				
			NXPrintf(output, "  %3d]  %2d:%02d %s  \t%s"
					"\t%s\\par}", 
				[ev present],  
				temp,
				[ev min], 
				([ev hour]>11)?"pm":"am",
				[ev message], annvTemp);
			}

		[ev readEvent : [ev next]]; 
		}   
	
		
	NXPrintf(output,
		"{\\f0\\par        -----------------------\\par}\n");	
	
	lastday = -1;		// Make it an illegal day value
			    		
	/* Print all remaining events according to priority */
	while ( [ev present] != 0)
		{
		// If the priority is high enough 
		// (or if it is the first event), 
		// then we will print this event
		// otherwise we skip it.
		if( [ev priority] < priorityCutOff && [ev previous] != 0)
			{
			#ifdef DEBUG
				fprintf(stderr,"Skipped %d\n", [ev present]);
			#endif
			[ev readEvent : [ev next]]; 	
			continue;
			}
		
		// If the event before was not on the
		// same day as the event
		// now, then print a line to space it somewhat
		if( lastday != [ev mday])	
			{
			NXPrintf(output, "{\\f0\\par\\b %s\\par}\n",
				ascMyDate([ev time]));
			lastday = [ev mday];
			}
				
		if( [ev anniversary]>0)		// An anniversary event
			{				
			// If it is just a 
			//once every _1_ event then we can print that
			if( [ev anniversary] % 100 > 1)
				sprintf(annvTemp, "(Every %d %s)",
				[ev anniversary] % 100, 
				annv[ ( [ev anniversary] / 100) ] );
			else
				sprintf(annvTemp, "(%s)", 
					annv2[ ( [ev anniversary] / 100) ]);
			}
		else
			strcpy(annvTemp , "");

		if( [ev priority] > [global highPriority])
			NXPrintf(output, "{\\f0\\b ");
		else
			NXPrintf(output, "{\\f0 ");
	
		if( [global militaryTime])
			NXPrintf(output, 
				"  %3d]  %2d:%02d  "
				"\t%s\t%s\\par}", 
				[ev present], [ev hour], [ev min],
				[ev message], annvTemp);
		else
			{
			temp = [ev hour];
			
			if( temp > 12 )
				temp -= 12;
			if( temp == 0 )
				temp = 12;
				
			NXPrintf(output, "  %3d]  %2d:%02d %s  \t%s"
				"\t%s\\par}", 
				[ev present], temp, [ev min], 
				([ev hour]>11)?"pm":"am",
				[ev message], annvTemp);
			}
			
		[ev readEvent : [ev next]]; 		
		}   
	
	NXPrintf(output, "}\n");	
	NXSeek(output, 0, NX_FROMSTART);
	[eventText readRichText:output]; 
	[eventText hideCaret];		// for some reason the Text
					// object sometimes leaves a caret...

	NXCloseMemory(output, NX_FREEBUFFER);  
	return self;
}

- viewPopUpChanged:sender
{	
	switch( [[viewPopUp itemList] selectedRow])
		{
		case 2:
			priorityCutOff = [global highPriority];
			break;
		case 1:
			priorityCutOff = [global lowPriority];
			break;
		case 0:
		default:
			priorityCutOff = 0;
			break;
		}
	#ifdef DEBUG
		fprintf(stderr, "Priority changed to %d.... (tag = %d)\n",
		 	priorityCutOff, [[viewPopUp itemList] selectedRow]);
	#endif
	[self listUpdate: self];
	return self;
}

- timeUpdate:sender
{	
	if( [self isVisible])
		[dateForm setStringValue : ascMyTime( (struct tm*) timeNow(), 
				showSeconds, militaryTime) at:0];

	return self;
}
		

- monthUpdate: sender
{
	monthNow = timeNow()->tm_mon;
	yearNow = timeNow()->tm_year;
	[self monthRedraw];
	return self;
}

- monthRedraw
{	
	if( [self isVisible] )
		{
		showCalendar( monthNow,   yearNow, thisMonthText);
		showCalendar( monthNow+1, yearNow, nextMonthText);
		showCalendar( monthNow-1, yearNow, lastMonthText);
		}
	return self;
}

- monthPrevious: sender
{
	monthNow --;
	if( monthNow < 0)
		{
		monthNow += 12;
		yearNow --;
		}
	[self monthRedraw];
	return self;
}

- monthNext: sender
{
	monthNow ++;
	if( monthNow > 11)
		{
		monthNow -= 12;
		yearNow ++;
		}
	[self monthRedraw];
	return self;
}


// Procedure:	showCalendar
// Arguments:	month, year; Show the month calendar for this date
//		id cal;		Put it up on this Text view.
// Description:	Writes up a small month calendar for the particular month.
//		If it is this month, bold face (high-light) today.
void showCalendar(int month, int year, id cal)
{
	NXStream	*in; 
	int day;
	
	if( month == timeNow()->tm_mon && year == timeNow() -> tm_year)
		day = timeNow()->tm_mday;
	else
		day = 0;

	if( month < 0)
		{
		month = 12;
		year --;
		}
	else
		{
		if( month > 11)
			{
			month = 1;
			year ++;
			}
		else
			month ++;
		}
	#ifdef  DEBUG
		fprintf(stderr,"%s: Opening %d:%d for calendar.\n",
				PROGNAME, month, year);
	#endif
	
	in = NXOpenMemory(NULL, 0, NX_READWRITE );
	
	printCalendarRTF( day, month, 1900+ year, in,
			FONTNAME_MONTHS, FONTSIZE_MONTHS);
	NXSeek(in, 0, NX_FROMSTART);
	[cal setRetainedWhileDrawing: YES];
	[cal readRichText:in]; 
	NXCloseMemory(in, NX_FREEBUFFER); 	
}
@end

