/*	You may freely copy, distribute and reuse the code in this example.
 *	NeXT disclaims any warranty of any kind, expressed or implied, as to
 *	its fitness for any particular use.
 */

#import "CallController.h"

@implementation CallController : Object

/* 
 * Purpose: Initialize the CallController
 *
 * Inherited from Object, overridden by CallController
 * to initialize callTable--the HashTable that holds CallRecords.  
 *
 * Looks for the file "call.log" in the application's main bundle.
 * If not found, concatenates the filename "call.log" to the path 
 * to the main bundle, so that the file may be saved in the main bundle 
 * by the saveCall: method.    
 * If the file "call.log" in the main bundle can be opened as a typed stream, 
 * reads the stream, and assigns its contents (a HashTable containing 
 * CallRecords) to the callTable instance variable.
 * If the file can't be opened, creates a new instance of HashTable and 
 * assigns it to the callTable. 
 */

- init
{
    NXTypedStream *callStream;
    BOOL fileFound;

    [super init];
    fileFound = [[NXBundle mainBundle] 
	getPath:callFilePath forResource:"call" ofType:"log"];
    if (!fileFound) {
	strcat(callFilePath,"/call.log"); // used in saveCall: as the file path
    }
    callStream = NXOpenTypedStreamForFile(callFilePath, NX_READONLY);
    if (callStream) {
	callTable = NXReadObject(callStream);
	NXCloseTypedStream(callStream);
    }
    else {
	callTable = [[HashTable alloc] initKeyDesc:"*" valueDesc:"@"];
    }
    return self;
}


/* Purpose: Initialize YourCall's user interface after unarchiving
 *
 * This method is an "informal protocol" implemented CallController.
 * An awakeFromNib message is sent to each object in a user interface archive
 * after all objects have been unarchived.
 * Through this method, CallController prepares the user interface to accept 
 * input.  
 * This code first selects the first field in the customer form.
 * It then puts the Call Information window in front of any others on 
 * the screen.
 */

- awakeFromNib
{
  [customerForm selectText:self];
  [[customerForm window] makeKeyAndOrderFront:self];
  return self;
}


/*
 * Purpose: Retrieve a call from the database.  
 *
 * Takes the customer name currently entered in customerFrom, 
 * looks up the corresponding CallRecord in the callTable HashTable, and
 * displays that record in the call form with the name field selected.  
 * If no such record is found, or if no name is entered, 
 * displays an attention panel.  
 */

- retrieveCall:sender
{
    const char *fetchName;
    CallRecord *fetchRecord = nil;

    fetchName = [customerForm stringValueAt:0]; 
    if (fetchName && strlen(fetchName)) {
	fetchRecord = [callTable valueForKey:fetchName];
	if (fetchRecord) {
	    [customerForm setStringValue:[fetchRecord street] at:1]; 
	    [customerForm setStringValue:[fetchRecord city] at:2]; 
	    [customerForm setStringValue:[fetchRecord state] at:3]; 
	    [customerForm setStringValue:[fetchRecord phone] at:4]; 
	    [questionText setStringValue:[fetchRecord question]];
	    [answerText setStringValue:[fetchRecord answer]];
	    [customerForm selectText:self];
	}
	else {
	    NXRunAlertPanel("Search Failed", "Customer %s not found", 
		NULL, NULL, NULL, fetchName);
	}
    }
    else {
	NXRunAlertPanel("Search Failed", "Please enter a customer name", 
	    NULL, NULL, NULL);
    }
    return self;
}


/*
 * Purpose: Save the information in the form to the database
 *
 * Reads the name from the form and tests whether it contains a valid string. 
 * If the name string exists, creates a new CallRecord object, 
 * reads data from the Call Information form, writes it in the new CallRecord,
 * and stores the CallRecord in the callTable, using customer name as the key. 
 * Opens the typed stream callStream, writes the callTable to the stream,  
 * then saves the stream in the file "call.log" in the application's 
 * main bundle.
 */

- saveCall:sender
{
    const char *formName = NULL;
    CallRecord *newRecord;
    NXTypedStream *callStream;

    formName = [customerForm stringValueAt:0];
    if (formName && strlen(formName)){
	newRecord = [[CallRecord alloc] init];
	[newRecord setName:[customerForm stringValueAt:0]];
	[newRecord setStreet:[customerForm stringValueAt:1]];
	[newRecord setCity:[customerForm stringValueAt:2]];
	[newRecord setState:[customerForm stringValueAt:3]];
	[newRecord setPhone:[customerForm stringValueAt:4]];
	[newRecord setQuestion:[questionText stringValue]];
 	[newRecord setAnswer:[answerText stringValue]];
	[callTable insertKey:[newRecord name] value:newRecord]; 
	callStream = NXOpenTypedStreamForFile(callFilePath, NX_WRITEONLY);
	if (callStream) {
	    NXWriteObject(callStream, callTable);
	    NXCloseTypedStream(callStream);
	}
	return self;
    }
    else return nil;
}


/*
 * Purpose: Begin a new call entry
 *
 * Clears the text in the Call Information form by setting all entries to NULL, 
 * without saving the data.  
 * Places the cursor in the first field of the customerForm.  
 */

- clearForm:sender;
{
    [customerForm setStringValue:NULL at:0];
    [customerForm setStringValue:NULL at:1];
    [customerForm setStringValue:NULL at:2];
    [customerForm setStringValue:NULL at:3];
    [customerForm setStringValue:NULL at:4];
    [questionText setStringValue:NULL];
    [answerText setStringValue:NULL];
    [customerForm selectText:self];
    return self;
}


/*
 * Purpose: Display the application's Info panel
 *
 * Displays the panel, loading its interface file first if it hasn't 
 * yet been loaded.
 *
 * To add this enhancement to your application (after completing the  
 * steps in Chapter 2):
 *
 * 1.  Open the YourCall.nib file in Interface Builder.  
 *
 * 2.  From the Interface Builder menu, choose Project/New Module/New InfoPanel 
 *
 * 3.  Modify the contents of the panel.
 *
 * 4.  Save the panel as "InfoPanel.nib"
 *
 * 5.  Open the CallController.h and CallController.m files and add this 
 *     method.
 *
 * 6.  From the files display in Interface Builder, Choose Classes, 
 *     then CallController, then Parse
 * 
 * 7.  Control drag from the menu's Info item to the CallController
 *
 * 8.  Double-click on CallController's -showInfoPanel: method
 *
 * 9.  Save the interface file in Interface Builder, then click Yes in the
 *     attention panel to add the file to the project.  
 */

- showInfoPanel:sender
{
    if (!infoPanel)
        [NXApp loadNibSection:"InfoPanel.nib" owner:self];
    [infoPanel makeKeyAndOrderFront:self];
    return self;
}


/* 
 * Purpose: Free the CallController
 *
 * Inherited from Object, overridden by CallController to
 * free the callTable HashTable, which in turn frees all CallRecords.  
 */

- free
{
    [callTable free];
    return [super free];
}

@end
