#include "kui.hxx"
#include "ktermin.hxx"
#include "kregedit.hxx"
#include "ksysmets.hxx"
#include "khwndset.hxx"
#include "kdwnload.hxx"
#include "ikextern.h"

extern "C" {
#include <windows.h> 
#include <process.h> 
#include "ikui.h"
}




// there is only one K_GLOBAL shared by all objects.
// this is used so that C functions (mostly wndprocs) have access to
// the KWin class pointers
//
K_GLOBAL* kglob = 0;
Kui* kui = 0;
KRegistryEdit* kreg = 0;

static HANDLE hevKuiInitialized = NULL;

const char KWinClassName[] = "KERMIT95:UI";
const char CmdTitle[] = "K95 Command Window";
const char TermTitle[] = "K95 Terminal Window";
const char CServerTitle[] = "K95 Client Server Window";

void KuiWindowThread( void* param );

/*------------------------------------------------------------------------
------------------------------------------------------------------------*/
int KuiInit( void* hInstance, struct _kui_init * kui_init )
{
    // The following code was used to create 
    //char* filename = "\\latin2.ttf"; //"e:\\kui\\fonts\\temp.ttf";
    //char* outfile = "\\latin2.fot"; //"e:\\kui\\fonts\\tempout.fot";
    //HRSRC src = FindResource( (HINSTANCE)hInstance, MAKEINTRESOURCE(IDR_FONTLAT2), RT_FONT );
    //DWORD size = SizeofResource( (HINSTANCE)hInstance, src );
    //HGLOBAL hglobal = LoadResource( (HINSTANCE)hInstance, src );
    //LockResource( hglobal );

    //HANDLE file = CreateFile( filename, GENERIC_WRITE, 0, NULL
    //                          , CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL );

    //DWORD numread = 0;
    //BOOL b = WriteFile( file, hglobal, size, &numread, NULL );

    //CloseHandle( file );

    //b = CreateScalableFontResource( 1, outfile, filename, NULL );
    //int numadded = AddFontResource( outfile );

    //DeleteFile( filename );



    // intialize K_GLOBAL
    //
    kglob = new K_GLOBAL;
    memset( kglob, '\0', sizeof(K_GLOBAL) );

    kglob->hInst = (HINSTANCE)hInstance;
    kglob->hwndset = new KHwndSet();
    kglob->sysMets = new KSysMetrics();

    // read initial window placement settings from the registry
    //
    kreg = new KRegistryEdit();
    if (kui_init->pos_init) {
	kglob->settings[Terminal_Left] = kui_init->pos_x;
        kglob->settings[Terminal_Top]  = kui_init->pos_y;
        kglob->settings[Command_Left] = (DWORD)CW_USEDEFAULT;
        kglob->settings[Command_Top]  = 0L;
        kglob->settings[CServer_Left] = (DWORD)CW_USEDEFAULT;
        kglob->settings[CServer_Top]  = 0L;
    } else {
	// kreg->getCoordinates( kglob );
        kglob->settings[Terminal_Left] = (DWORD)CW_USEDEFAULT;
        kglob->settings[Terminal_Top]  = 0L;
        kglob->settings[Command_Left] = (DWORD)CW_USEDEFAULT;
        kglob->settings[Command_Top]  = 0L;
        kglob->settings[CServer_Left] = (DWORD)CW_USEDEFAULT;
        kglob->settings[CServer_Top]  = 0L;
    }

    kreg->getFontinfo( kglob );
    if (kui_init->face_init)
	strcpy(kglob->faceName,kui_init->facename);
    if (kui_init->font_init)
	kglob->fontHeight = kui_init->font_size;

    kglob->noMenuBar = kui_init->nomenubar;
    kglob->noToolBar = kui_init->notoolbar;
    kglob->noStatus  = kui_init->nostatusbar;
    kglob->nCmdShow  = kui_init->nCmdShow;
    kglob->mouseEffect = kui_init->resizeMode;
    kglob->noClose   = kui_init->noclose;
    // kglob->mouseEffect = TERM_MOUSE_CHANGE_DIMENSION;
    // kglob->mouseEffect = TERM_MOUSE_NO_EFFECT;
    // kglob->mouseEffect = TERM_MOUSE_CHANGE_FONT;

    return TRUE;
}

/*------------------------------------------------------------------------
------------------------------------------------------------------------*/
HANDLE KuiThreadInit( void* hInstance )
{   
    DWORD rc = 0;
    hevKuiInitialized = CreateEvent( NULL, TRUE, FALSE, NULL );
    _beginthread( KuiWindowThread, 65535, hInstance );
    rc = WaitForSingleObjectEx( hevKuiInitialized, (ULONG) -1L, TRUE );
    if ( rc != WAIT_OBJECT_0 )
        return FALSE;
    CloseHandle(hevKuiInitialized);
    hevKuiInitialized = NULL;
    // the window should now be initialized so change the default to 
    // change dimension.
    return kui->getTerminal()->getClient()->hwnd();
}
   
/*------------------------------------------------------------------------
------------------------------------------------------------------------*/
int KuiThreadCleanup( void* hInstance )
{
    //Cleanup Embedded Font
    //BOOL b = RemoveFontResource( outfile );
    //DeleteFile( outfile );

    if ( IsZoomed(kui->getTerminal()->hwnd()) || 
         IsIconic(kui->getTerminal()->hwnd())) {
#ifndef CKT_NT35_OR_31
        ShowWindowAsync(kui->getTerminal()->hwnd(), SW_RESTORE);
#else
        ShowWindow(kui->getTerminal()->hwnd(), SW_RESTORE);
#endif
        Sleep(50);
    }

    kui->savePositions();
    kui->cleanup();

    // save last window positions
    //
    kreg->setCoordinates( kglob );
    kreg->setFontinfo( kglob );
    delete kreg;

    return TRUE;
}

void KuiSetTerminalStatusText(int item, char * buf)
{
    if (kui)
        kui->getTerminal()->setStatusText(item,buf);
}

void KuiSetTerminalConnectButton(int on) 
{
    if (kui) {
        kui->getTerminal()->setConnectMode(on);
    }
}

void 
KuiSetTerminalPosition( int x, int y)
{
    if ( kui )
        SetWindowPos(kui->getTerminal()->hwnd(), 0, x, y, 0, 0,
#ifndef CKT_NT35_OR_31
                      SWP_ASYNCWINDOWPOS |
#endif
                      SWP_NOZORDER | SWP_NOSIZE );
}

void 
KuiSetTerminalSize( int x, int y)
{
    if ( kui ) {
        RECT rect;
        GetWindowRect(kui->getTerminal()->hwnd(),&rect);
        if ( x == 0 )
            x = rect.right - rect.left;
        if ( y == 0 )
            y = rect.bottom - rect.top;
        SetWindowPos(kui->getTerminal()->hwnd(), 0, 0, 0, x, y,
#ifndef CKT_NT35_OR_31
                      SWP_ASYNCWINDOWPOS |
#endif
                      SWP_NOZORDER | SWP_NOMOVE );
        msleep(50);
        kui->getTerminal()->getClient()->syncSize();
    }
}

void 
KuiSetTerminalResizeMode(int x)
{
    if ( kui )
        SendMessage(kui->getTerminal()->hwnd(), WM_COMMAND,
                     x == TERM_MOUSE_CHANGE_FONT ? ID_ACTION_RESIZE_FONT : 
                     x == TERM_MOUSE_CHANGE_DIMENSION ? ID_ACTION_RESIZE_DIMENSION :
                     ID_ACTION_RESIZE_NONE, 0);
}

int
KuiGetTerminalResizeMode(void)
{
    return kglob->mouseEffect;
}

void 
KuiSetTerminalRunMode(int x)
{
    if ( kui ) {
        switch ( x ) {
        case 2: /* minimize */
            ShowWindow(kui->getTerminal()->hwnd(), SW_MINIMIZE);
            break;
        case 3: /* maximize */
            ShowWindow(kui->getTerminal()->hwnd(), SW_MAXIMIZE);
            break;
        case 1: /* restore */
        default:
            ShowWindow(kui->getTerminal()->hwnd(), SW_RESTORE);
            break;
                
        }
    }
}

int KuiGetTerminalRunMode() {
    long ret = GetWindowLong(kui->getTerminal()->hwnd(), GWL_STYLE);

    if (ret & WS_MINIMIZE) return 2;
    return 1;
}

int widthToChars(int width) {
    return width / kui->getTerminal()->getKFont()->getFontW();
}

int heightToChars(int height) {
    return height / kui->getTerminal()->getKFont()->getFontSpacedH();
}

void KuiGetTerminalMaximisedSize(BOOL inChars, int* width, int* height) {
#ifdef SPI_GETWORKAREA
    // SPI_GETWORKAREA is new in Windows 95 and Visual C++ 4.0. Windows NT 4.0
    // apparently does handle it, but returns the dimensions of the entire
    // screen including the task bar, rather than the dimensions of the screen
    // area excluding the task bar.
    RECT rec;
    BOOL r = SystemParametersInfo(
            SPI_GETWORKAREA,0, &rec, 0);
    if (r) {
        *width = rec.right - rec.left;
        *height = rec.bottom - rec.top;
    } else
#endif /* SPI_GETWORKAREA */
    {
        // On NT 3.x
        *width = GetSystemMetrics( SM_CXSCREEN );
        *height = GetSystemMetrics( SM_CYSCREEN );
    }

    if (inChars) {
        *width = widthToChars(*width);
        *height = heightToChars(*height);
    }
}

int
KuiFileDialog(char * title, char * def, char * result, int rlen,
                  BOOL downloadButton, BOOL openFile)
{
    if ( kui ) {
        KDownLoad download( kglob, downloadButton, openFile );
        download.setTitle(title);
        download.setInitialFileName(def);
        download.createWin( kui->getTerminal() );
        download.show();
        if ( !download.wasCancelled() ) {
            ckstrncpy(result, download.getSelectedFileName(), rlen);
            return 1;
        }
    }
    return 0;
}

/*------------------------------------------------------------------------
------------------------------------------------------------------------*/
void KuiWindowThread( void* hInstance )
{
    kui = new Kui( (HINSTANCE)hInstance );
    kui->init();
    SetEvent(hevKuiInitialized);
    kui->start();
    delete kui;

    delete kglob->hwndset;
    delete kglob->sysMets;
    delete kglob;
} 

/*------------------------------------------------------------------------
------------------------------------------------------------------------*/
void KuiSetProperty( int propid, intptr_t param1, intptr_t param2 )
{
    if( kui )
        kui->setProperty( propid, param1, param2 );
}

/*------------------------------------------------------------------------
------------------------------------------------------------------------*/
int KuiGetProperty( int propid, void* out )
{
    if( kui )
        return kui->getProperty( propid, out );
    return 0;
}

/*------------------------------------------------------------------------
------------------------------------------------------------------------*/
#ifdef CK_SHELL_NOTIFY
void KuiShowNotification(int icon, char* title, char * message) {
    kui->getTerminal()->showNotification(icon, title, message);
}
#endif /* CK_SHELL_NOTIFY */

void KuiRefreshTerminal() {
    kui->getTerminal()->getClient()->getDrawInfo();
}

BOOL KuiRenderToEmfFile(int vmode, char* filename) {
    return kui->getTerminal()->getClient()->renderToEmfFile(vmode, filename);
}

#ifdef CK_SAVE_TO_IMAGE
BOOL KuiRenderToBmpFile(int vmode, char* filename) {
    return kui->getTerminal()->getClient()->renderToBmpFile(vmode, filename);
}

#ifdef CK_HAVE_GDIPLUS
BOOL KuiRenderToPngFile(int vmode, char* filename) {
    return kui->getTerminal()->getClient()->renderToPngFile(vmode, filename);
}
BOOL KuiRenderToGifFile(int vmode, char* filename) {
    return kui->getTerminal()->getClient()->renderToGifFile(vmode, filename);
}

BOOL KuiRenderSoftFontToFile(int fontbuffer, const char* filename) {
    return kui->getTerminal()->getClient()->saveFontBuffer(
        fontbuffer, filename, L"image/png");
}
#endif /* CK_HAVE_GDIPLUS */
#endif /* CK_SAVE_TO_IMAGE */
