/*
 *        spComponentMain.h
 */

#ifndef __SPMAIN_H
#define __SPMAIN_H

#if defined(_MSC_VER)
#pragma comment ( lib, "comctl32" )
#pragma comment ( lib, "htmlhelp" )
#pragma comment ( lib, "uxtheme" )
#pragma comment ( lib, "gdiplus" )
#if defined(__SPGL_H)
#pragma comment ( lib, "Glu32" )
#pragma comment ( lib, "opengl32" )
#endif /* defined(__SPGL_H) */
#endif /* defined(_MSC_VER) */

#include <stdio.h>
#if defined(_WIN32) && !defined(USE_MOTIF) && !defined(GTK)
#include <windows.h>
#if defined(USE_CONSOLE) && !defined(__CYGWIN32__)
#include <io.h>
#include <fcntl.h>
#endif /* defined(USE_CONSOLE) && !defined(__CYGWIN32__) */
#elif defined(ANDROID) /* defined(_WIN32) && !defined(USE_MOTIF) && !defined(GTK) */
#include <jni.h>
#endif

#if defined(__cplusplus) && !defined(SP_DISABLE_ABBREVIATION)
#define SP_DISABLE_ABBREVIATION 1
#define SP_ENABLE_ABBREVIATION_LATER 1
#endif
    
#include <sp/spBase.h>
#include <sp/spComponentDefs.h>

#if defined(SP_ENABLE_ABBREVIATION_LATER)
#undef SP_DISABLE_ABBREVIATION 
#undef SP_ENABLE_ABBREVIATION_LATER    
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if defined(_WIN32) && !defined(USE_MOTIF) && !defined(GTK)
extern int spWinMainInitialize(HINSTANCE hThisInst, HINSTANCE hPrevInst, int nWinMode);
extern char **spGetArgv(LPSTR lpszArgs, int *argc);
extern void spFreeArgv(int argc, char **argv);

int spMain(int argc, char *argv[]);

int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, 
                   LPSTR lpszArgs, int nWinMode)
{
    int flag;
    int argc;
    char **argv;

#if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC)
    _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
    spsetstdio(stdin, stdout, stderr);
    
    if (spWinMainInitialize(hThisInst, hPrevInst, nWinMode) == FALSE) {
        return FALSE;
    }
    argv = spGetArgv(lpszArgs, &argc);
    
#if defined(USE_CONSOLE) && !defined(__CYGWIN32__)
    /* Don't use this code except for debug */
    {
        AllocConsole();
        
#if defined(_MSC_VER) && (_MSC_VER >= 1900/*VS2015*/)
        freopen("CONOUT$", "w", stderr);
        setvbuf(stderr, NULL, _IONBF, 0);
#else
        {
            int hcrt;
            FILE *hf;
        
            /* the following code doesn't work in apps built by VS2015 (universal CRT environment) */
            if ((hcrt = _open_osfhandle((intptr_t)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT)) != -1) {
                if ((hf = _fdopen(hcrt, "w")) != NULL) {
                    *stderr = *hf;
                    setvbuf(stderr, NULL, _IONBF, 0);
                }
            }
        }
#endif
    }
#endif
    
    flag = spMain(argc, argv);
    spFreeArgv(argc, argv);

    return flag;
}

#elif defined(ANDROID)
int spMain(int argc, char *argv[]);
    
#elif defined(IPHONE)

extern int spMainCocoaTouch(int argc, char *argv[]);
    
int main(int argc, char *argv[])
{
    return spMainCocoaTouch(argc, argv);
}
    
#elif defined(COCOA)
    
int spMain(int argc, char *argv[]);
extern void spInitializeFromMainCocoa(void);
    
int main(int argc, char *argv[])
{
    spInitializeFromMainCocoa();

#if 0
    {
        int i;
        for (i = 0; i < argc; i++) {
            spDebug(-10, "main", "argv[%d] = %s\n", i, argv[i]);
        }
    }
#endif
    
    if (argc == 2 && strneq(argv[1], "-psn", 4)) {
        --argc;
    }
    return spMain(argc, argv);
}

#elif defined(MACOS) && !defined(COCOA)

#pragma import on
int spMain(int argc, char *argv[]);
    
extern void spInitializeFromMainMac(void);
#pragma import off

#if defined(HIGH_LEVEL_EVENT)

#pragma import on

extern spBool spInitializeMac(int argc, char **argv, spMainFunc func);
extern void spWaitHighLevelEventMac(void);

#pragma import off

int main(int argc, char *argv[])
{
    spInitializeFromMainMac();
    
    if (spInitializeMac(argc, argv, spMain) == SP_FALSE) {
        return spMain(argc, argv);
    } else {
        spWaitHighLevelEventMac();
    }
    
    return 0;
}

#else  /* defined(HIGH_LEVEL_EVENT) */

int main(int argc, char *argv[])
{
    spInitializeFromMainMac();
    
    return spMain(argc, argv);
}

#endif /* !defined(HIGH_LEVEL_EVENT) */

#else
#define spMain main
#endif
    
#ifdef __cplusplus
}  /* Close scope of 'extern "C"' declaration */
#endif

#endif /* __SPMAIN_H */
