#import <Foundation/Foundation.h>
#import <CoreServices/CoreServices.h>
#import <Carbon/Carbon.h>
#import <stdlib.h>
#import <stdio.h>
#import <unistd.h>
#import <errno.h>
#import <sys/types.h>
#import <sys/stat.h>


// The path to the command file, which we'll delete on death (if it exists)
static char s_command_path[PATH_MAX];

static void die(const char *format, ...) {
    va_list ap;
    va_start(ap, format);
    vfprintf(stderr, format, ap);
    va_end(ap);
    fputc('\n', stderr);

    if (s_command_path[0] != '\0') {
        unlink(s_command_path);
    }

    exit(EXIT_FAILURE);
}

static void launch_fish_with_applescript(NSString *fish_binary_path)
{
    // load the script from a resource by fetching its URL from within our bundle
    NSString *path = [[NSBundle mainBundle] pathForResource:@"launch_fish" ofType:@"scpt"];
    if (! path) die("Couldn't get path to launch_fish.scpt");

    NSURL *url = [NSURL fileURLWithPath:path isDirectory:NO];
    if (! url) die("Couldn't get URL to launch_fish.scpt");

    NSDictionary *errors = nil;
    NSAppleScript *appleScript = [[NSAppleScript alloc] initWithContentsOfURL:url error:&errors];
    if (! appleScript) die("Couldn't load AppleScript");

    // create the first parameter
    NSAppleEventDescriptor *firstParameter =
            [NSAppleEventDescriptor descriptorWithString:fish_binary_path];

    // create and populate the list of parameters (in our case just one)
    NSAppleEventDescriptor *parameters = [NSAppleEventDescriptor listDescriptor];
    [parameters insertDescriptor:firstParameter atIndex:1];

    // create the AppleEvent target
    ProcessSerialNumber psn = {0, kCurrentProcess};
    NSAppleEventDescriptor *target =
    [NSAppleEventDescriptor
            descriptorWithDescriptorType:typeProcessSerialNumber
            bytes:&psn
            length:sizeof(ProcessSerialNumber)];

    // create an NSAppleEventDescriptor with the script's method name to call,
    // this is used for the script statement: "on show_message(user_message)"
    // Note that the routine name must be in lower case.
    NSAppleEventDescriptor *handler = [NSAppleEventDescriptor descriptorWithString:
            [@"launch_fish" lowercaseString]];

    // create the event for an AppleScript subroutine,
    // set the method name and the list of parameters
    NSAppleEventDescriptor *event =
            [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite
                    eventID:kASSubroutineEvent
                    targetDescriptor:target
                    returnID:kAutoGenerateReturnID
    transactionID:kAnyTransactionID];
    [event setParamDescriptor:handler forKeyword:keyASSubroutineName];
    [event setParamDescriptor:parameters forKeyword:keyDirectObject];

    // call the event in AppleScript
    if (![appleScript executeAppleEvent:event error:&errors])
    {
        // report any errors from 'errors'
        NSLog(@"Oops: %@", errors);
    }

    [appleScript release];
}

/* This approach asks Terminal to open a script that we control */
int main(void) {

    @autoreleasepool {
        /* Get the fish executable. Make sure it's absolute. */
        NSURL *fish_executable = [[NSBundle mainBundle] URLForResource:@"fish" withExtension:@""
                                                          subdirectory:@"base/usr/local/bin"];
        if (! fish_executable)
            die("Could not find fish executable in bundle");

        launch_fish_with_applescript([fish_executable path]);
    }

    /* If we succeeded, it will clean itself up */
    return 0;
}
