#include <libc.h>
#import <AppKit/AppKit.h>
#include "../qcommon/qcommon.h"

cvar_t	sys_nostdout = {"sys_nostdout","1"};

double		curtime;

/*
===============================================================================

				REQUIRED SYS FUNCTIONS

===============================================================================
*/


void Sys_Mkdir (char *path)
{
	if (mkdir (path, 0777) != -1)
		return;
	if (errno != EEXIST)
		Com_Error (ERR_FATAL, "mkdir %s: %s",path, strerror(errno)); 
}


/*
================
Sys_DoubleTime
================
*/
double Sys_DoubleTime (void)
{
	struct timeval tp;
	struct timezone tzp;
	static int		secbase;

	gettimeofday(&tp, &tzp);
	
	if (!secbase)
	{
		secbase = tp.tv_sec;
		return tp.tv_usec/1000000.0;
	}
	
        curtime = (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;

        return curtime;
}

/*
================
Sys_Error
================
*/
void Sys_Error (char *error, ...)
{
	va_list		argptr;
	char		string[1024];
	
// change stdin to non blocking
	fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);

	va_start (argptr,error);
	vsprintf (string,error,argptr);
	va_end (argptr);
	printf ("Fatal error: %s\n",string);
	
	if (!NSApp)
	{	// appkit isn't running, so don't try to pop up a panel
		exit (1);
	}
        NSRunAlertPanel (@"Fatal error",[NSString stringWithCString: string]
                         ,@"exit",NULL,NULL);
	[NSApp terminate: NULL];
        exit(1);
}

/*
================
Sys_Printf
================
*/
void Sys_Printf (char *fmt, ...)
{
	va_list		argptr;
	char		text[1024], *t_p;
	int			l, r;
	
	if (sys_nostdout.value)
		return;
		
	va_start (argptr,fmt);
	vsprintf (text,fmt,argptr);
	va_end (argptr);
	
	l = strlen(text);
	t_p = text;
	
// make sure everything goes through, even though we are non-blocking
	while (l)
	{
		r = write (1, text, l);
		if (r != l)
			sleep (0);
		if (r > 0)
		{
			t_p += r;
			l -= r;
		}
	}
}

/*
================
Sys_Quit
================
*/
void Sys_Quit (void)
{
// change stdin to blocking
	fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY);

	if (!NSApp)
		exit (0);		// appkit isn't running

        [NSApp terminate:nil];
}


/*
================
Sys_Init
================
*/
void Sys_Init(void)
{
    moncontrol(0);	// turn off profiling except during real Quake work

// change stdin to non blocking
     fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY);	
}


extern	NSWindow	*vid_window_i;

void Sys_AppActivate (void)
{
    [vid_window_i makeKeyAndOrderFront: nil];
}

void Sys_SetWindowText (char *text)
{

    [vid_window_i setTitle: [[NSString alloc] initWithCString: text] ];
}


/*
================
Sys_SendKeyEvents

service any pending appkit events
================
*/
void Sys_SendKeyEvents (void)
{
	NSEvent	*event;

	while ( (event = [NSApp
		nextEventMatchingMask: 	0xffffffff 
		untilDate:		0
                 inMode:		@"NSDefaultRunLoopMode"
		dequeue:		YES] ) )
	{
		[NSApp	sendEvent: event];
	}
}


/*
================
Sys_ConsoleInput

Checks for a complete line of text typed in at the console, then forwards
it to the host command processor
================
*/
char *Sys_ConsoleInput (void)
{
	static char	text[256];
	int		len;

	len = read (0, text, sizeof(text));
	if (len < 1)
		return NULL;
	text[len-1] = 0;	// rip off the /n and terminate
	
	return text;
}

int	myargc;
char	*myargv[128];
static char	basedir[1024];

void FindBasedir (int argc, char **argv)
{
    int		i;
    char	*s;

    myargc = argc;
    memcpy (myargv, argv, argc*sizeof(argv[0]));

    for (i=1 ; i<argc ; i++)
        if (!strcmp(argv[i], "-basedir"))
            return;

    strcpy (basedir, argv[0]);
    s = basedir+strlen(basedir)-1;
    while (s != basedir)
        {
        if (*s == '/')
            {
            *s = 0;
            break;
            }
        s--;
        }

    myargv[myargc++] = "-basedir";
    myargv[myargc++] = basedir;
    printf ("basedir: %s\n", basedir);
}

/*
=============
main
=============
*/
void main (int argc, char **argv)
{
    int		frame;
    NSAutoreleasePool *pool;
	double		oldtime, t;
        
    pool =[[NSAutoreleasePool alloc] init];
        
	Sys_Init ();
   FindBasedir (argc, argv);     
    Qcommon_Init (myargc, myargv);
	Cvar_RegisterVariable (&sys_nostdout);
        
        CL_Init ();
        SV_Init ();

        [pool release];

        oldtime = Sys_DoubleTime ();
        while (1)
        {
            pool =[[NSAutoreleasePool alloc] init];
            
            if (++frame > 10)
                moncontrol(1);// profile only while we do each Quake frame

            t = Sys_DoubleTime () - oldtime;
            oldtime = curtime;
            CL_Frame (t);
            SV_Frame (t);
            moncontrol(0);

            [pool release];
        }
}

