#import <libc.h>
#import <appkit/Application.h>
#import <appkit/Speaker.h>
#import <appkit/Listener.h>
#import <objc/HashTable.h>
#import "IBinaryD.h"

static NXAtom rtfControlWord;
static NXAtom fileExtension;
static NXAtom pasteboardType;
static NXImage *icon;
static NXImage *defaultImage;

// IBinaryD is used to embedded files of unknown type into a document.
// The embedded object is represented as a file icon in the document.
// The workspace manager is used to supply the file icon.
// A double click on this icon will cause workspace manager to open the
// file.

// ## REWRITE! ## might be better to send a message than use extern
extern HashTable *listOfTempFiles;

@implementation IBinaryD

+ initialize
{
    rtfControlWord = NXUniqueStringNoCopy("MMbin");
    fileExtension = NXUniqueStringNoCopy("bin");
    pasteboardType = NXUniqueStringNoCopy("Binary Format");
    // ## REWRITE! ## should provide default icon
    icon = nil;
    defaultImage = nil;
    return(self);
}

+ (NXAtom)rtfControlWord
{
    return(rtfControlWord);
}

+ (NXAtom)fileExtension
{
    return(fileExtension);
}

+ (NXAtom)pasteboardType
{
    return(pasteboardType);
}

+ setIcon:(NXImage *)theIcon
{
    icon = theIcon;
    return(self);
}

+ (NXImage *)icon
{
    return(icon);
}

- setImage:(NXImage *)theIcon
{
    image = theIcon;
    return(self);
}

//****************************************************************************
// return image to be displayed.
//****************************************************************************

- (NXImage *)image
{
    char path[256];
    char *data;
    int length;
    int maxLen;
    NXStream *outStream;
    char stringBuffer[512];
    int flag;
    NXStream *iconStream;


    if (image != nil) {
        return(image);
    }
    
    if (stream == NULL) {
        return(defaultImage);
    }

    // get WorkSpace Manager to provide the file icon  
    // First create head of this file on disk
    NXGetMemoryBuffer(stream, &data, &length, &maxLen);
    if ((outStream = NXOpenMemory(NULL, 0, NX_WRITEONLY)) == NULL) {
        return(defaultImage);
    }
    NXWrite(outStream, data, 1024);
    sprintf(path, "/tmp/%.250s", key);
    if (NXSaveToFile(outStream, path) != 0) {
        NXCloseMemory(outStream, NX_FREEBUFFER);
        return(defaultImage);
    }
    NXCloseMemory(outStream, NX_FREEBUFFER);

    // add executable permissions if neccessary
    sprintf(stringBuffer, "file %.250s | grep executable > /dev/null", path);
    if (system(stringBuffer) == 0) {
        chmod(path, 0700);
    } else {
        chmod(path, 0600);
    }

    // get WorkSpace Manager to provide file icon
    [[NXApp appSpeaker] setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
    [[NXApp appSpeaker] getFileIconFor:path TIFF:&data TIFFLength:&length
        ok:&flag];
    unlink(path);
    if (flag != YES) {
        return(defaultImage);
    }
    iconStream = NXOpenMemory(data, length, NX_READONLY);
    image = [[NXImage alloc] initFromStream:iconStream];
    NXCloseMemory(iconStream, NX_FREEBUFFER);
    return(image);
}

//****************************************************************************
// get WorkSpace Manager to open the file.
//****************************************************************************
- performDoubleClickAction:sender
{
    char stringBuffer[512];
    const char *filename;
    NXStream *tempStream;
    int flag;

    sprintf(stringBuffer, "/tmp/%.506s", [self key]);
    filename = NXCopyStringBuffer(stringBuffer);
    tempStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
    [self writeToStream:tempStream];
    NXSaveToFile(tempStream, filename);
    NXCloseMemory(tempStream, NX_FREEBUFFER);
    [[NXApp appSpeaker] setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
    [[NXApp appSpeaker] openFile:filename ok:&flag];
    [listOfTempFiles insertKey:filename value:nil];
    return(self);
}

- free
{
    if (image != nil) {
        [image free];
    }
    return([super free]);
}

@end
