/** SDLMain.m - main entry point for our Cocoa-ized SDL app
    Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
    Non-NIB-Code & other changes: Max Horn <max@quendi.de>
  */

#import "SDL.h"
#import "SDLMain.h"
#import "Preferences.h"

#define SDL_main stellaMain
extern int stellaMain(int argc, char* argv[]);

static int    gArgc;
static char** gArgv;
static BOOL   gFinderLaunch;
static BOOL   gCalledAppMainline = FALSE;


// The main class of the application, the application's delegate
@implementation SDLMain

// ----------------------------------------------------------------------------
static SDLMain* sharedInstance = nil;

+ (SDLMain*) sharedInstance {
    return sharedInstance;
}


// ----------------------------------------------------------------------------
// Set the working directory to the .app's parent directory
- (void) setupWorkingDirectory:(BOOL)shouldChdir
{
  if (shouldChdir)
  {
    char parentdir[MAXPATHLEN];
    CFURLRef url  = CFBundleCopyBundleURL(CFBundleGetMainBundle());
    CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url);
    if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8*)parentdir, MAXPATHLEN))
    {
      chdir(parentdir);   /* chdir to the binary app's parent */
    }
    CFRelease(url);
    CFRelease(url2);
  }
}


// ----------------------------------------------------------------------------
/**
  * Catch document open requests...this lets us notice files when the app
  *  was launched by double-clicking a document, or when a document was
  *  dragged/dropped on the app's icon. You need to have a
  *  CFBundleDocumentsType section in your Info.plist to get this message,
  *  apparently.
  *
  * Files are added to gArgv, so to the app, they'll look like command line
  *  arguments. Previously, apps launched from the finder had nothing but
  *  an argv[0].
  *
  * This message may be received multiple times to open several docs on launch.
  *
  * This message is ignored once the app's mainline has been called.
  */
- (BOOL)application:(NSApplication*)theApplication openFile:(NSString*)filename
{
  const char* temparg;
  size_t arglen;
  char* arg;
  char** newargv;

  if (!gFinderLaunch)     // MacOS is passing command line args.
    return FALSE;
  if (gCalledAppMainline) // app has started, ignore this document.
    return FALSE;

  temparg = [filename UTF8String];
  arglen = SDL_strlen(temparg) + 1;
  arg = (char*) SDL_malloc(arglen);
  if (arg == NULL)
    return FALSE;

  newargv = (char **) realloc(gArgv, sizeof (char*) * (gArgc + 2));
  if (newargv == NULL)
  {
    SDL_free(arg);
    return FALSE;
  }
  gArgv = newargv;

  SDL_strlcpy(arg, temparg, arglen);
  gArgv[gArgc++] = arg;
  gArgv[gArgc] = NULL;
  return TRUE;
}


// ----------------------------------------------------------------------------
// Called when the internal event loop has just started running
- (void) applicationDidFinishLaunching: (NSNotification *) note
{
  int status;

  // Set the working directory to the .app's parent directory
  [self setupWorkingDirectory:gFinderLaunch];

  // Hand off to main application code
  gCalledAppMainline = TRUE;
  status = SDL_main (gArgc, gArgv);

  // We're done, thank you for playing
  exit(status);
}

@end

static int IsRootCwd()
{
  char buf[MAXPATHLEN];
  char *cwd = getcwd(buf, sizeof (buf));
  return (cwd && (strcmp(cwd, "/") == 0));
}

static int IsTenPointNineOrLater()
{
  /* -instancesRespondToSelector is available in 10.9, but it says that it's
   available in 10.10. Either way, if it's there, we're on 10.9 or higher:
   just return true so we don't clobber the user's console with this. */
  if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) {
    return 1;
  }
  /* Gestalt() is deprecated in 10.8, but I don't care. Stop using SDL 1.2. */
  SInt32 major, minor;
  Gestalt(gestaltSystemVersionMajor, &major);
  Gestalt(gestaltSystemVersionMinor, &minor);
  return ( ((major << 16) | minor) >= ((10 << 16) | 9) );
}

static int IsFinderLaunch(const int argc, char **argv)
{
  const int bIsNewerOS = IsTenPointNineOrLater();
  /* -psn_XXX is passed if we are launched from Finder in 10.8 and earlier */
  if ( (!bIsNewerOS) && (argc >= 2) && (strncmp(argv[1], "-psn", 4) == 0) ) {
    return 1;
  } else if ((bIsNewerOS) && (argc == 1) && IsRootCwd()) {
    /* we might still be launched from the Finder; on 10.9+, you might not
     get the -psn command line anymore. Check version, if there's no
     command line, and if our current working directory is "/". */
    return 1;
  }
  return 0;  /* not a Finder launch. */
}

#ifdef main
#  undef main
#endif

// Main entry point to executable - should *not* be SDL_main!
int main (int argc, char* argv[])
{
	static Preferences *myPrefs;

  // Copy the arguments into a global variable
  // This is passed if we are launched by double-clicking
  if (IsFinderLaunch(argc, argv))
  {
    gArgv = (char**) SDL_malloc(sizeof(char*) * 2);
    gArgv[0] = argv[0];
    gArgv[1] = NULL;
    gArgc = 1;
    gFinderLaunch = YES;
  }
  else
  {
    gArgc = argc;
    gArgv = (char**) SDL_malloc(sizeof(char*) * (argc+1));
    for (int i = 0; i <= argc; i++)
      gArgv[i] = argv[i];
    gFinderLaunch = NO;
  }

	myPrefs = [Preferences sharedInstance];

  NSApplicationMain (argc, (const char**)argv);

  return 0;
}
