/* indent:4  tabsize:8  font:fixed-width */

#import "Preferences.h"

#define TIFF_IMAGE 1
#define EPS_IMAGE 2
#define OTHER_IMAGE 3


@implementation Preferences

static int checkImageType(const char *filename)
{
    if(strcmp(strrchr(filename, '.'), ".tiff") == 0){
	return TIFF_IMAGE;
    }
    if(strcmp(strrchr(filename, '.'), ".tif") == 0){
	return TIFF_IMAGE;
    }
    if(strcmp(strrchr(filename, '.'), ".TIFF") == 0){
	return TIFF_IMAGE;
    }
    if(strcmp(strrchr(filename, '.'), ".TIF") == 0){
	return TIFF_IMAGE;
    }
    if(strcmp(strrchr(filename, '.'), ".eps") == 0){
	return EPS_IMAGE;
    }
    if(strcmp(strrchr(filename, '.'), ".EPS") == 0){
	return EPS_IMAGE;
    }
    else{
	return OTHER_IMAGE;
    }

    return NULL;
}

static void convertColorToString(NXColor aColor,char *aString)
{
    float r,g,b;
  
    NXConvertColorToRGB(aColor, &r, &g, &b);
    sprintf(aString, "%6.4f %6.4f %6.4f", r, g, b );
    return;
}

static NXColor convertStringToColor(const char *aString)
{
    float r,g,b;
  
    if(aString)
        sscanf(aString, "%f %f %f", &r, &g, &b);
  
    return NXConvertRGBToColor(r,g,b);
}

static BOOL IncludesType(const NXAtom *types, NXAtom type)
{
	if (types) while (*types) if (*types++ == type) return YES;
	return NO;
}


- init
{
    BOOL statusPanelUp=NO;
    const NXDefaultsVector solitaireDefaults =
    {
        {"backgroundColor", "0.0 0.2 0.1333"},
        {"cardSize", "0"},
	{"cardBack", "0"},
	{"preDrawCards", "1"},
	{"imageFileName", NULL},
        {NULL, NULL}
    };

    NXRegisterDefaults([NXApp appName], solitaireDefaults);

    backgroundColor = convertStringToColor(NXGetDefaultValue([NXApp appName], 
                                           "backgroundColor"));
    cardSize = atoi(NXGetDefaultValue([NXApp appName], "cardSize"));
    cardBack = atoi(NXGetDefaultValue([NXApp appName], "cardBack"));
    preDrawCards = atoi(NXGetDefaultValue([NXApp appName], "preDrawCards"));

    [self showPreferences:self];

    if(NXGetDefaultValue([NXApp appName], "imageFileName")){
    	statusPanelUp = YES;
    	[messageField setStringValue:"Converting Custom Back Image..."];
    	[statusPanel makeKeyAndOrderFront:nil];
	NXPing();
    	imageFileName = NXCopyStringBuffer(NXGetDefaultValue([NXApp appName], "imageFileName"));
	[self setNewImage:self];
    }
    
    if(preDrawCards){
        statusPanelUp = YES;
    	[messageField setStringValue:"Pre-Drawing Cards..."];
    	[statusPanel makeKeyAndOrderFront:nil];
	NXPing();

    	if(cardSize == CS_SMALL)
	    [[SmallCard class] drawCardImages];	
	else
       	    [[Card class] drawCardImages];
    }

    if(statusPanelUp) [statusPanel orderOut:nil];
    return self;
}


- defaults:sender
{
    [backgroundColorWell setColor:NXConvertRGBToColor(0.0, 51.0/255.0, 34.0/255.0)];
    [cardSizeMatrix selectCellWithTag:CS_SMALL];
    [cardBackMatrix selectCellWithTag:CS_DEFAULT];
    [self saveColor:self];
    [self saveCardSize:self];
    [self saveCardBack:self];
    
    return self;
}


- saveColor:sender
{
    char buffer[80];
    
    backgroundColor = [backgroundColorWell color];

    convertColorToString(backgroundColor, buffer);
    NXWriteDefault([NXApp appName], "backgroundColor", buffer);
    return self;
}


- saveCardSize:sender
{
    char buffer[80];

    cardSize = [cardSizeMatrix selectedTag];
    sprintf(buffer, "%d", cardSize);
    NXWriteDefault([NXApp appName], "cardSize", buffer);
    
    if(preDrawCards){
    	if(cardSize == CS_SMALL)
	    [[SmallCard class] drawCardImages];	
	else
       	    [[Card class] drawCardImages];
    }

    return self;
}


- saveCardBack:sender
{
    char buffer[80];

    cardBack = [cardBackMatrix selectedTag];
    sprintf(buffer, "%d", cardBack);
    NXWriteDefault([NXApp appName], "cardBack", buffer);
    return self;
}


- savePreDrawState:sender
{
    char buffer[80];
    
    preDrawCards = [preDrawSwitch state];
    sprintf(buffer, "%d", preDrawCards);
    NXWriteDefault([NXApp appName], "preDrawCards", buffer);

    if(preDrawCards){
    	if(cardSize == CS_SMALL)
	    [[SmallCard class] drawCardImages];	
	else
       	    [[Card class] drawCardImages];
    }
    else{
    	[[Card class] freeCardImages];
	[[SmallCard class] freeCardImages];
    }
    return self;
}


- setNewImage:sender
{
    id originalRep=nil;
    id buttonCell;
    NXRect imageRect;
    NXRect largeRect = {{0,0},{91.0, 153.0}};
    NXRect smallRect = {{0,0},{67.0, 114.0}};
    NXStream *stream;
    int imageType = checkImageType(imageFileName);
    
    if(imageType == TIFF_IMAGE){
	if(stream = NXMapFile(imageFileName, NX_READONLY)){
	    originalRep = [[NXBitmapImageRep allocFromZone:[self zone]] 
			    initFromStream:stream];
	    [originalRep getSize:&(imageRect.size)];
	}
	else{
	    NXRunAlertPanel("Custom Image Error",
	    "Could not find the image file, %s, for the custom card back.",
	    "OK", NULL, NULL, imageFileName);
	    return self;
	}
    }
    else if(imageType == EPS_IMAGE){
	if(stream = NXMapFile(imageFileName, NX_READONLY)){
	    originalRep = [[NXEPSImageRep allocFromZone:[self zone]] 
			    initFromStream:stream];
	    [originalRep getBoundingBox:&imageRect];
	    [originalRep setOpaque:YES];
	}
	else{
	    NXRunAlertPanel("Custom Image Error",
	    "Could not find the image file, %s, for the custom card back.",
	    "OK", NULL, NULL, imageFileName);
	    return self;
	}
    }
    else if(imageType == OTHER_IMAGE){
	id pasteboard;
	char *data;
	int length;

	pasteboard = [Pasteboard newByFilteringFile:imageFileName];
	[pasteboard readType:NXTIFFPboardType data:&data length:&length];
	stream = NXOpenMemory(data, length, NX_READONLY);
	if(length){
	    originalRep = [[NXBitmapImageRep allocFromZone:[self zone]] 
			    initFromStream:stream];
	    [originalRep getSize:&(imageRect.size)];
	}
	NXCloseMemory(stream, NX_SAVEBUFFER);
	[pasteboard deallocatePasteboardData:data length:length];
	if(!originalRep){
	    NXRunAlertPanel("Custom Image Error",
	    "Error in converting or could not find the image file, %s, for the custom card back.",
	    "OK", NULL, NULL, imageFileName);
	    return self;
	}
    }
    else{
	NXRunAlertPanel("Custom Image Error",
	"Image type not supported in Solitaire.",
	"OK", NULL, NULL);
    	return self;
    }
    
    NXWriteDefault([NXApp appName], "imageFileName", imageFileName);
    imageRect.origin.x = 0.0; imageRect.origin.y = 0.0;

    if(cardBackImage) [cardBackImage free];
    if(sCardBackImage) [sCardBackImage free];
    
    cardBackImage = [[NXImage allocFromZone:[self zone]] initSize:&(largeRect.size)];
    [cardBackImage setScalable:YES];
    [cardBackImage setUnique:YES];
    [cardBackImage useCacheWithDepth:NX_DefaultDepth];
    if([cardBackImage lockFocusOn:[cardBackImage lastRepresentation]]){
	[originalRep drawIn:&largeRect];
	[cardBackImage unlockFocus];
    }
    
    sCardBackImage = [[NXImage allocFromZone:[self zone]] initSize:&(smallRect.size)];
    [sCardBackImage setScalable:YES];
    [sCardBackImage setUnique:YES];
    [sCardBackImage useCacheWithDepth:NX_DefaultDepth];
    if([sCardBackImage lockFocusOn:[sCardBackImage lastRepresentation]]){
	[originalRep drawIn:&smallRect];
	[sCardBackImage unlockFocus];
    }
    
    buttonCell = [cardBackMatrix findCellWithTag:3];
    [buttonCell setIconPosition:NX_ICONONLY];
    [buttonCell setImage:sCardBackImage];
    [buttonCell setEnabled:YES];
    [originalRep free];
    return self;
}
    

- showPreferences:sender
{
    if (!preferencesPanel)
    {
        int depth;
    	const char *const types[] = {NXFilenamePboardType};
	
        [NXApp loadNibSection:"Preferences.nib" owner:self withNames:NO fromZone:[self zone]];
        [preferencesPanel setFrameAutosaveName:"PrefPanel"];
	[preferencesPanel registerForDraggedTypes:(const char *const*)&types count:1];
	[backgroundColorWell setColor:backgroundColor];
	[cardSizeMatrix selectCellWithTag:cardSize];
	[cardBackMatrix selectCellWithTag:cardBack];
	[preDrawSwitch setState:preDrawCards];
	
	if ((depth = [preferencesPanel depthLimit]) == NX_DefaultDepth)
	    depth = [Window defaultDepthLimit];
	    
	if (depth == NX_TwoBitGrayDepth)
	    [backgroundColorWell setEnabled:NO];
	else
	    [backgroundColorWell setEnabled:YES];
    
	if(sCardBackImage){
	    id buttonCell = [cardBackMatrix findCellWithTag:3];
	    [buttonCell setIconPosition:NX_ICONONLY];
	    [buttonCell setImage:sCardBackImage];
	    [buttonCell setEnabled:YES];
	}
    }
    
    if(sender != self) [preferencesPanel makeKeyAndOrderFront:nil];

    return self;
}


- (CardSize)returnCardSize
{
    return cardSize;
}


- (CardBack)returnCardBack
{
    return cardBack;
}


- (NXColor)returnBackgroundColor
{
    return backgroundColor;
}


- returnImageForSize:(CardSize)aSize
{
    if(aSize == CS_SMALL)
    	return sCardBackImage;
    	
    return cardBackImage;
}


- (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
{
    foundFile = NO;
    return [self draggingUpdated:sender];
}


- (NXDragOperation)draggingUpdated:(id <NXDraggingInfo>)sender
{
    int length;
    Pasteboard *pboard;
    char *data, *file, *tab;
    const char *const *type;
    const char *const *imageFileTypes=[NXImage imageFileTypes];

    pboard = [sender draggingPasteboard];
    if(IncludesType([pboard types], NXFilenamePboardType)){
	[pboard readType:NXFilenamePboardType data:&data length:&length];
	file = data;
	while(file){
	    if(tab = strchr(file, '\t')) 
		*tab = '\0';
	    if(strrchr(file, '.') != NULL){
		type = imageFileTypes;
		while(type){
		    if(strcmp((strrchr(file, '.')+1), type)){
			foundFile = YES;
			break;
		    }
		    type = type++;
		}
	    }
	    file = tab ? ++tab : NULL;
	}
    }

    if(!foundFile) 
	    return NX_DragOperationNone;
    else
	    return NX_DragOperationCopy;
}


- (BOOL)prepareForDragOperation:(id <NXDraggingInfo>)sender
{
    if(foundFile) return YES;
    return NO;
}


- (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
{
    int length;
    Pasteboard *pboard;
    char *data, *file, *tab;
    const char *const *type;
    const char *const *imageFileTypes=[NXImage imageFileTypes];

    pboard = [sender draggingPasteboard];
    if(IncludesType([pboard types], NXFilenamePboardType)){
	[pboard readType:NXFilenamePboardType data:&data length:&length];
	file = data;
	while(file){
	    if(tab = strchr(file, '\t')) 
		*tab = '\0';
	    if(strrchr(file, '.') != NULL){
		type = imageFileTypes;
		while(type){
		    if(strcmp((strrchr(file, '.')+1), type)){
		    	if(imageFileName) NX_FREE(imageFileName);
			imageFileName = NXCopyStringBuffer(file);
			break;
		    }
		    type = type++;
		}
	    }
	    file = tab ? ++tab : NULL;
	}
	[pboard deallocatePasteboardData:data length:length];
    }
    [NXApp activateSelf:YES];
    return YES;
}


- concludeDragOperation:(id <NXDraggingInfo>)sender
{
    [self perform:@selector(setNewImage:) 
	with:self  
	afterDelay:0
	cancelPrevious:NO];
    foundFile = NO;	// reset for next dragging operation
    return self;
}


@end
