/*
 * LEGAL NOTICE
 *
 * Copyright (c) 1994 WSC Investment Services, Inc.
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND WSC INVESTMENT SERVICES (WSCIS)
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT
 * SHALL WSCIS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 
 * USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Users of this software agree to return to WSCIS any improvements 
 * or extensions that they make and grant WSCIS the rights to 
 * redistribute these changes.
 *
 * Export of this software is permitted only after complying with the
 * regulations of the U.S. Deptartment of Commerce relating to the
 * Export of Technical Data.
 */

#import "HKGnatsReport.h"
#import "HKSendPr.h"
#import <hk/HKString.h>
#import <errno.h>
#import <hk/HKDelimitedTable.h>
#import <appkit/NXHelpPanel.h>

@interface TextFieldCell(CheckIt)
- (const char *)stringValue;
@end

@implementation TextFieldCell(CheckIt)
- (const char *)stringValue;
{
	const char * ret = [super stringValue];
	return ret ? ret : "";
}
@end

@implementation HKGnatsReport

static id sharedInstance = nil;

- setupMenu;
{
	int i, count;
	id menuMatrix, menuCell;
	id menu = [NXApp mainMenu];

	if (installedMenu) return self;
	if (!menu) {
		return nil;
	} else {
		installedMenu = YES;
	}
	
	menuMatrix= [menu itemList];
	count = [menuMatrix cellCount];
	for(i = 0; (menuCell = [menuMatrix cellAt:i :0]); i++) {
		if(strncmp([menuCell title],"Info",strlen("Info")) == 0) {
			if ([menuCell hasSubmenu]){
				id submenu = [menuCell target];
				[[submenu addItem:"Bug Report..."
					action:@selector(showPanel:)
					keyEquivalent:0] setTarget:self];
			} else {
				id newMenu= [[Menu alloc] initTitle:"Info"];
				SEL oldAction = [menuCell action];
				id cell;
				[menuMatrix removeRowAt:i andFree:NO];
				[menuMatrix insertRowAt:i];
				[[menuMatrix cellAt:i:0] setTitle:"Info"];
				cell = [newMenu addItem:"Info..."
						action:oldAction
						keyEquivalent:0];
				// the old switcheroo
				[[[[newMenu itemList] cellList] replaceObject:cell
								with:menuCell] free];
				cell = [newMenu addItem:"Bug Report..."
						action:@selector(showPanel:)
						keyEquivalent:0];
				[cell setTarget:self];
				[menu setSubmenu:newMenu forItem:[menuMatrix cellAt:i:0]];
			}
			break;
		}
	}
	// if (!menuCell) then add Info > Bug Report at the top
	return self;
}

- awakeFromNib;
{
	float left,right,top,bottom;
	[self setupMenu];
        [problemText getMarginLeft:&left right:&right top:&top bottom:&bottom];
        left += 3.0;
        top += 3.0;
        [problemText setMarginLeft:left right:right top:top bottom:bottom];
	return self;
}

- (BOOL)loadBundle:bundle;
{
	char path[MAXPATHLEN+1];
	BOOL errors = NO;
	/*
	 * We have to load the categories before the nib
	 */
	if (![bundle getPath:path forResource:"categories" ofType:""]){
		NXRunAlertPanel([self name],"Couldn't open \"categories\" in \"%s\" (%s)",0,0,0,
				[bundle directory],strerror(errno));
		errors = YES;
	} else {
		[categories readFromFilename:path];
	}
	/*
	 * The nib comes second so we can configure it from
	 * the categories.
	 */
	if (![bundle getPath:path forResource:"HKGnatsReport" ofType:"nib"]){
		NXRunAlertPanel([self name],"Cound't find nib \"HKGnatsReport.nib\" (%s)",0,0,0,
				strerror(errno));
		errors = YES;
	} else if (!([NXApp loadNibFile:path owner:self])){
		NXRunAlertPanel([self name],"Couldn't open nib \"%s\" (%s)",0,0,0,
				path,strerror(errno));
		errors = YES;
	}
#if 0
	if (![bundle getPath:path forResource:"HKGnatsBundleHelp" ofType:""]){
		NXRunAlertPanel([self name],"Couldn't find HKGnatsBundleHelp in \"%s\" (%s)",0,0,0,
				[bundle directory],strerror(errno));
	} else {
		[[NXHelpPanel new] addSupplement:"TableOfContents.rtf" inPath:path];
	}
#endif
	[panel setTitle:[categories line:0 field:1]];
	return errors;
}


- init;
{
	BOOL errors = NO;
	if (sharedInstance) {
		[NXApp delayedFree:self];
		return sharedInstance;
	} else {
		id bundle;
		char path[MAXPATHLEN+1];
		[super init];
		sprintf(path,"%s/%s",[[NXBundle mainBundle] directory],"HKGnatsReport.bundle");
		if (!(bundle = [[NXBundle alloc] initForDirectory:path])){
			NXRunAlertPanel([self name],"Couldn't open bundle \"%s\" (%s).",0,0,0,
					path,strerror(errno));
			errors = YES;
		} else {
			sendPr = [[HKSendPr alloc] init];
			categories = [[HKDelimitedTable alloc] init];
			[sendPr setup];
			errors = [self loadBundle:bundle];
			[bundle free];
		}
		if (!errors) {
			[self setupMenu];
			current = problem = [[HKString alloc] init];
			howToRepeat = [[HKString alloc] init];
			possibleFix = [[HKString alloc] init];
			return self;
		} else {
			[NXApp delayedFree:self];
			return nil;
		}
	}
}

- free;
{
	if (sharedInstance != self) {
		return [super free];
	} else {
		return nil;
	}
}

- changeExplanation:sender;
{
	int tag = [[sender selectedCell] tag];
	const char * exp = [categories line:tag field:1];
	[panel setTitle:exp];
	return self;
}

// configure popup lists
- setCategoryPop:sender;
{
	id matrix = [[sender target] itemList];
	int i,count = [categories count];
	categoryPop = sender;
	[matrix renewRows:count cols:1];
	for(i=0;i<count;i++){
		id cell = [matrix cellAt:i:0];
		[cell setTitle:[categories line:i field:0]];
		[cell setTag:i];
		[cell setTarget:self];
		[cell setAction:@selector(changeExplanation:)];
	}
	[categoryPop setTitle:[[matrix cellAt:0:0] title]];
	return self;
}

- setClassPop:sender;
{
	id matrix = [[sender target] itemList];
	classPop = sender;
	[[[matrix cellAt:0:0] setTitle:"Software Bug"] setTag:HK_SoftwareBug];
	[[[matrix cellAt:0:1] setTitle:"Documentation Bug"] setTag:HK_DocumentationBug];
	[[[matrix cellAt:0:2] setTitle:"Change Request"] setTag:HK_ChangeRequest];
	[[[matrix cellAt:0:3] setTitle:"Support"] setTag:HK_Support];
	return self;
}

- setPriorityPop:sender;
{
	id matrix = [[sender target] itemList];
	priorityPop = sender;
	[[[matrix cellAt:0:0] setTitle:"Low"] setTag:HK_LowPriority];
	[[[matrix cellAt:0:1] setTitle:"Medium"] setTag:HK_MediumPriority];
	[[[matrix cellAt:0:2] setTitle:"High"] setTag:HK_HighPriority];
	return self;
}


- setSeverityPop:sender;
{
	id matrix = [[sender target] itemList];
	severityPop = sender;
	[[[matrix cellAt:0:0] setTitle:"Non-Critical"] setTag:HK_NonCriticalSeverity];
	[[[matrix cellAt:0:1] setTitle:"Serious"] setTag:HK_SeriousSeverity];
	[[[matrix cellAt:0:2] setTitle:"Critical"] setTag:HK_CriticalSeverity];
	return self;
}


#define SUBMITTER "GnatsSubmitter"
#define ORGANIZATION "ORGANIZATION"
#define REPORTTO "GnatsReportTo"
- set:field from:(const char *)name;
{
	const char * sub = getenv(name);
	if (!sub) sub = NXReadDefault("Global",name);
	if (!sub) sub = NXReadDefault([NXApp appName],name);
	[field setStringValue:sub];
	return self;
}

// configure fields
- setSubmitterField:sender;
{
	[self set:sender from:SUBMITTER];
	submitterField = sender;
	return self;
}

- setOrganizationField:sender;
{
	[self set:sender from:ORGANIZATION];
	organizationField = sender;
	return self;
}

- setReportToField:sender;
{
	[self set:sender from:REPORTTO];
	if (!strlen([sender stringValue])){
		[sender setStringValue:"bugs"];
	}
	reportToField = sender;
	return self;
}

// actions
- clear:sender;
{
	[summaryField setStringValue:""];
	[problemText setText:""];
	[problem setStringValue:""];
	[howToRepeat setStringValue:""];
	[possibleFix setStringValue:""];
	return self;
}

- (const char *)_version;
{
	const char * release = 0;
	id del = [NXApp delegate];
	if (del != self && [del respondsTo:@selector(version)]){
		release = (const char *)[del perform:@selector(version)];
	} else {
		release = [NXApp appName];
	}
	return release;
}

- change:sender;
{
	int len = [problemText textLength];
	id other;
	char text[len+1];
	[problemText getSubstring:text start:0 length:len];
	text[len]='\0';

	[current setStringValue:text];
	switch([[sender selectedCell] tag]){
	default:
	case 0:
		other = problem;
		break;
	case 1:
		other = howToRepeat;
		break;
	case 2:
		other = possibleFix;
		break;
	}
	if (current!=other){
		current = other;
		[problemText setText:[current stringValue]];
	}
	return self;
}

// could be better about this
- writeAndTest:(const char *)defaultName with:(const char *)value;
{
	NXWriteDefault([NXApp appName],defaultName,value);
	return self;
}

- check;
{
	[self change:controlMatrix];
	if (!strlen([summaryField stringValue])){
		return nil;
	}
	if (!strlen([problem stringValue])){
		return nil;
	}
	[self writeAndTest:ORGANIZATION with:[organizationField stringValue]];
	[self writeAndTest:SUBMITTER with:[submitterField stringValue]];
	[self writeAndTest:REPORTTO with:[reportToField stringValue]];
	return self;
}

- submit:sender;
{
	if ([self check]){
		[sendPr setEmailTo:[reportToField stringValue]];
		[sendPr setSubmitterID:[submitterField stringValue]];
		[sendPr setOrganization:[organizationField stringValue]];
		[sendPr setConfidential:[confidentialSwitch state]];
		[sendPr setSynopsis:[summaryField stringValue]];
		[sendPr setSeverity:[severityPop selectedTag]];
		[(HKSendPr *)sendPr setPriority:[priorityPop selectedTag]];
		[sendPr setBugClass:[classPop selectedTag]];
		[sendPr setCategory:[categoryPop title]];
		[sendPr setRelease:[self _version]];
		[sendPr setDescription:[problem stringValue]];
		[sendPr setHowToRepeat:[howToRepeat stringValue]];
		[sendPr setHowToFix:[possibleFix stringValue]];
		if (![sendPr send]){
			NXRunAlertPanel([self name],"Problem sending bug report.",0,0,0);
		} else {
			[panel performClose:self];
		}
	} else {
		NXRunAlertPanel([self name],"The problem report is incomplete.",0,0,0);
	}
	return self;
}

- showPanel:sender;
{
	[panel makeKeyAndOrderFront:self];
	return self;
}


// set these programatically
- setReportTo:(const char *)name;
{
	[reportToField setStringValue:name];
	return self;
}

- setSubmitterID:(const char *)name;
{
	[submitterField setStringValue:name];
	return self;
}

//
// Only if he's appDelegate.
//
- appDidInit:sender;
{
	[self showPanel:self];
	return self;
}

@end


	
