/*
 * w_misc.c : common routines for core windows
 *
 * Copyright (c) Yukihiko Aoki 1999, 2005
 * NetHack may be freely redistributed.  See license for details.
 *
 */

#include "hack.h"

#ifdef NH2K_EXTENDS

#include "win32api.h"
#include "w_main.h"
#include "res/resource.h"

/*
 * local functions
 */
static WINCONTROL *NDECL(DefaultControl);

/***************************************************************************************
 * error dialog
 ***************************************************************************************/
void PrintError(const char *format, ...)
{
    char buf[BUFSZ+1];
    va_list list;

    va_start(list, format);
    vsprintf(buf, format, list);
    va_end(list);

    MessageBox(NULL, buf, "NetHack", MB_OK|MB_ICONERROR);
}

/***************************************************************************************
 * get directory where executable file is
 ***************************************************************************************/
void GetModuleDirectory(char *buf, int len)
{
    char *ptr;

    GetModuleFileName(g_hInstance, buf, len);
    ptr = strrchr(buf, '\\');
    if(ptr) {
        *(ptr + 1) = '\0';
    }
}

/***************************************************************************************/
/* load display mode information list
/***************************************************************************************/
WINCONTROL *ListControlFiles(const char *dir)
{
    WIN32_FIND_DATA  find;
    WINCONTROL      *top = NULL, *tmp;
    char             tilepath[MAX_PATH + 1];
    HANDLE           hFileList;

    sprintf(tilepath, "%s%s\\*.ctl", dir, TILEDIR);
    hFileList = FindFirstFile(tilepath, &find);
    if(hFileList != INVALID_HANDLE_VALUE) {
        do {
            sprintf(tilepath, "%s%s\\%s", dir, TILEDIR, find.cFileName);
            tmp = LoadControlFile(tilepath, FALSE);
            if(tmp) {
                tmp->next = top;
                top = tmp;
            }
        }while(FindNextFile(hFileList, &find));
    }

    /* console mode is always selectable */
/* currently disabled */
/*
    tmp = DefaultControl();
    tmp->next = top;
    top = tmp;
*/

    FindClose(hFileList);

    return top;
}

/***************************************************************************************
 * load display type from specified file
 ***************************************************************************************/
WINCONTROL *LoadControlFile(char *filename, BOOL notice)
{
    WINCONTROL *info    = NULL;
    BOOL        success = FALSE;
    const char *section = "NHTILES";
    char       *key;
    char        buf[MAX_PATH];

    info = (WINCONTROL *)calloc(1, sizeof(WINCONTROL));
    if(info) {
        /* load description */
        key = "name";
        if(!GetPrivateProfileString(section, key, "", info->name, BUFSZ, filename)) {
            goto finish_load;
        }
        /* load type */
        key = "type";
        if(!(info->mode = GetPrivateProfileInt(section, key, 0, filename))) {
            goto finish_load;
        }
        /* load filename */
        key = "glyph_tile";
        if(!GetPrivateProfileString(section, key, "", buf, MAX_PATH, filename)) {
            goto finish_load;
        }
        GetModuleDirectory(info->glyph, MAX_PATH);
        strcat(info->glyph, TILEDIR);
        strcat(info->glyph, "\\");
        strcat(info->glyph, buf);

        /* load filename */
        key = "option_tile";
        if(!GetPrivateProfileString(section, key, "", buf, MAX_PATH, filename)) {
            goto finish_load;
        }
        strcat(info->option, TILEDIR);
        strcat(info->option, "\\");
        strcat(info->option, buf);

        /* load filename: optional */
        key = "effect_tile";
        if (GetPrivateProfileString(section, key, "", buf, MAX_PATH, filename)) {
            strcat(info->effect, TILEDIR);
            strcat(info->effect, "\\");
            strcat(info->effect, buf);

            /* load effect description: optional */
            key = "animation";
            GetPrivateProfileString(section, key, "", info->animation, BUFSZ, filename);
        }

        /* load single tile width */
        key = "cx";
        if(!(info->cx = GetPrivateProfileInt(section, key, 0, filename))) {
            goto finish_load;
        }
        /* load single tile height */
        key = "cy";
        if(!(info->cy = GetPrivateProfileInt(section, key, 0, filename))) {
            goto finish_load;
        }
        /* load default tile rect */
        key = "valid_rect";
        if(!GetPrivateProfileString(section, key, "", info->valid_rect, BUFSZ, filename)) {
            goto finish_load;
        }
        success = TRUE;

finish_load:
        if(!success) {
            if(notice) {
                PrintError("Error: invalid value(%s) in %s", key, filename);
            }
            free(info);
            info = NULL;
        }
    }else {
        PrintError("Error: memory allocation");
    }

    return info;
}

/*-------------------------------------------------------------------------------------
 * return default display type (ASCII Text Mode)
 *-------------------------------------------------------------------------------------*/
static WINCONTROL *DefaultControl()
{
    WINCONTROL *info;

    info = (WINCONTROL *)calloc(1, sizeof(WINCONTROL));
    if(info) {
        strcpy(info->name, "Win32 Console");
        info->mode = MODE_CONSOLE;
    }

    return info;
}

/***************************************************************************************/
/* dealloc display mode information list
/***************************************************************************************/
void FreeControl(WINCONTROL *list)
{
    WINCONTROL *tmp;

    while(list) {
        tmp = list->next;
        free(list);
        list = tmp;
    }
}

/***************************************************************************************/
/* 
/***************************************************************************************/
BOOL InitDisplayMode(WINCONTROL *info, void (*callbackProc)(int,int))
{
    BOOL result = FALSE;

    if(info) {
        switch(info->mode) {
        case MODE_CONSOLE:
           result = AllocConsole();
           choose_windows("tty");
           break;
        case MODE_GDI3D:
            result = GDI3D_init(info, callbackProc);
            GDI3D_func(&disp_procs);
            choose_windows("nh2k");
            break;
        case MODE_GDI2D:
            result = GDI2D_init(info, callbackProc);
            GDI2D_func(&disp_procs);
            choose_windows("nh2k");
            break;
        default:
            break;
        }
    }

    return result;
}

/***************************************************************************************
 * Register all window classes used in this game
 ***************************************************************************************/
BOOL RegisterNetHackWindows(HINSTANCE hinst)
{
    WNDCLASS wc;
    ATOM     ret;

    /* default values */
    wc.style         = CS_HREDRAW|CS_VREDRAW|CS_BYTEALIGNCLIENT|CS_PARENTDC;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hinst;
    wc.hIcon         = LoadIcon(hinst,"NHICON");
    wc.hCursor       = LoadCursor(NULL,IDC_ARROW);
    wc.lpszMenuName  = "MAIN_MENU";
    wc.hbrBackground = GetStockObject(BLACK_BRUSH);

    /* base window */
    wc.lpfnWndProc   = BaseWndProc;
    wc.lpszClassName = "NHBASE";
    ret = RegisterClass(&wc);

    /* following classes are base window's children */
    wc.lpszMenuName  = NULL;
    wc.hIcon         = NULL;

    /* main map window */
    wc.lpfnWndProc   = MapWndProc;
    wc.lpszClassName = "NHMAP";
    ret = RegisterClass(&wc);

    /* message window */
    wc.lpfnWndProc   = MesgWndProc;
    wc.lpszClassName = "NHMESG";
    ret = RegisterClass(&wc);

    /* menu and text window */
    wc.lpfnWndProc   = MenuWndProc;
    wc.lpszClassName = "NHMENU";
    ret = RegisterClass(&wc);

    /* status window */
    wc.lpfnWndProc   = StatWndProc;
    wc.lpszClassName = "NHSTAT";
    ret = RegisterClass(&wc);

    /* micro map window */
    wc.lpfnWndProc   = MicroWndProc;
    wc.lpszClassName = "NHMICRO";
    ret = RegisterClass(&wc);

    /* sub status window (icon and side) */
    wc.lpfnWndProc   = SubStatProc;
    wc.lpszClassName = "NHSUBSTAT";
    ret = RegisterClass(&wc);

    wc.lpfnWndProc   = AskWndProc;
    wc.lpszClassName = "NHASK";
    ret = RegisterClass(&wc);

    wc.lpfnWndProc   = CmdWndProc;
    wc.lpszClassName = "NHCmd";
    ret = RegisterClass(&wc);

    return TRUE;
}

/***************************************************************************************
 * Unregister window classes
 ***************************************************************************************/
BOOL UnregisterNetHackWindows(HINSTANCE hinst)
{
    UnregisterClass("NHBASE",    hinst);
    UnregisterClass("NHMAP",     hinst);
    UnregisterClass("NHMESG",    hinst);
    UnregisterClass("NHMENU",    hinst);
    UnregisterClass("NHSTAT",    hinst);
    UnregisterClass("NHMICRO",   hinst);
    UnregisterClass("NHSUBSTAT", hinst);
    UnregisterClass("NHASK",     hinst);
    UnregisterClass("NHCMD",     hinst);

    return TRUE;
}

/*-------------------------------------------------------------------------------------
 * 
 *-------------------------------------------------------------------------------------*/
BOOL GetBitmapSize(const char* filename, SIZE *size)
{
    HBITMAP hbmp = NULL;
    BITMAP bm;
    
    hbmp = LoadImage(
        NULL, filename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);

    if (hbmp != NULL) {
        GetObject(hbmp, sizeof(BITMAP), &bm);
        size->cx = bm.bmWidth;
        size->cy = bm.bmHeight;
        DeleteObject(hbmp);
        return TRUE;
    }
    
    return FALSE;
}

/***************************************************************************************/
/* Load skins
/***************************************************************************************/
BOOL LoadSkins(HINSTANCE hinst)
{
    BOOL success = FALSE;
    SIZE size;
    BOOL defskin = FALSE;
    char buf[MAX_PATH + 1];

    if (strlen(g_skindir) == 0) {
        defskin = TRUE;
    }

    g_resource = (WINRESOURCE *)calloc(1, sizeof(WINRESOURCE));
    if(g_resource) {

        g_resource->max_height = 0;

        /* Gold header */
        sprintf(buf, "%s\\%s", g_skindir, "gld_h.bmp");
        if (!defskin && GetBitmapSize(buf, &size)) {
            g_resource->gld_h = Tile_load(
                NULL, buf, size.cx, size.cy, NULL, NULL);
        } 
        if (g_resource->gld_h == NULL) {
			size.cx = STB_STAT_WIDTH;
            size.cy = STB_HEIGHT;
            g_resource->gld_h = Tile_load(
                hinst, "GLD_H", size.cx, size.cy, NULL, NULL);
        }
        g_resource->max_height = size.cy;

        /* Gold number */
        sprintf(buf, "%s\\%s", g_skindir, "gld_n.bmp");
        if (!defskin && GetBitmapSize(buf, &size)) {
            g_resource->gld_n = Tile_load(
                NULL, buf, (size.cx / 10), size.cy, NULL, NULL);
        } 
        if (g_resource->gld_n == NULL) {
			size.cx = STB_GOLD_WIDTH;
            size.cy = STB_HEIGHT;
            g_resource->gld_n = Tile_load(
                hinst, "GLD_N", size.cx, size.cy, NULL, NULL);
        }
        g_resource->max_height = max(g_resource->max_height, size.cy);

        /* Gold footer */
        sprintf(buf, "%s\\%s", g_skindir, "gld_f.bmp");
        if (!defskin && GetBitmapSize(buf, &size)) {
            g_resource->gld_f = Tile_load(
                NULL, buf, size.cx, size.cy, NULL, NULL);
        } 
		/* No default footer
        if (g_resource->gld_bmp == NULL) {
			size.cx = STB_STAT_WIDTH
            size.cy = STB_HEIGHT;
            g_resource->gld_f = Tile_load(
                hinst, "GLD_H", size.cx, size.cy, NULL, NULL);
        }
        g_resource->max_height = max(g_resource->max_height, size.cy);
		*/

        /* Special status */
        sprintf(buf, "%s\\%s", g_skindir, "stt.bmp");
        if (!defskin && GetBitmapSize(buf, &size)) {
            g_resource->stt_bmp = Tile_load(
                NULL, buf, (size.cx / 7), size.cy, NULL, NULL);
        }
        if (g_resource->stt_bmp == NULL) {
            size.cy = STB_HEIGHT;
            g_resource->stt_bmp = Tile_load(
                hinst, "STT_BMP", STB_STAT_WIDTH, STB_HEIGHT, NULL, NULL);
        }
        g_resource->max_height = max(g_resource->max_height, size.cy);

        /* Encumbered status */
        sprintf(buf, "%s\\%s", g_skindir, "enc.bmp");
        if (!defskin && GetBitmapSize(buf, &size)) {
            size.cy = size.cy / 6;
            g_resource->enc_bmp = Tile_load(
                NULL, buf, size.cx, size.cy, NULL, NULL);
        }
        if (g_resource->enc_bmp == NULL) {
            size.cy = STB_HEIGHT;
            g_resource->enc_bmp = Tile_load(
                hinst, "ENC_BMP", STB_ENC_WIDTH, STB_HEIGHT, NULL, NULL);
        }
        g_resource->max_height = max(g_resource->max_height, size.cy);

        /* Hunger status */
        sprintf(buf, "%s\\%s", g_skindir, "hun.bmp");
        if (!defskin && GetBitmapSize(buf, &size)) {
            size.cy = size.cy / 7;
            g_resource->hun_bmp = Tile_load(
                NULL, buf, size.cx, size.cy, NULL, NULL);
        }
        if (g_resource->hun_bmp == NULL) {
            size.cy = STB_HEIGHT;
            g_resource->hun_bmp = Tile_load(
                hinst, "HUN_BMP", STB_HUN_WIDTH, STB_HEIGHT, NULL, NULL);
        }
        g_resource->max_height = max(g_resource->max_height, size.cy);

        /* Micro map symbol */
        sprintf(buf, "%s\\%s", g_skindir, "sym.bmp");
        if (!defskin && GetBitmapSize(buf, &size)) {
            size.cx = size.cx / PLACE_NUM;
            g_resource->sym_bmp = Tile_load(
                NULL, buf, size.cx, size.cy, NULL, NULL);
        }
        if (g_resource->sym_bmp == NULL) {
            size.cy = 6;
            g_resource->sym_bmp = Tile_load(
                hinst, "SYM_BMP", 6, 6, NULL, NULL);
        }

        /* wall */
        sprintf(buf, "%s\\%s", g_skindir, "wall.bmp");
        if (!defskin && GetBitmapSize(buf, &size)) {
            g_resource->wal_bmp = Tile_load(
                NULL, buf, size.cx, size.cy, NULL, NULL);
        }

        /* menu buttons */
        g_resource->btn_bmp = LoadImage(
            hinst, "MENU_BMP", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);

        /* more */
        g_resource->mor_bmp = LoadImage(
            hinst, "MORE_BMP", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);

        success = TRUE;
    }
    return success;
}

/***************************************************************************************/
/* Free skins
/***************************************************************************************/
void FreeSkins()
{
    if (g_resource != NULL) {
        Tile_free(g_resource->gld_h);
        Tile_free(g_resource->gld_n);
        Tile_free(g_resource->gld_f);
        Tile_free(g_resource->stt_bmp);
        Tile_free(g_resource->enc_bmp);
        Tile_free(g_resource->hun_bmp);
        Tile_free(g_resource->sym_bmp);
        DeleteObject(g_resource->btn_bmp);
        DeleteObject(g_resource->mor_bmp);
        Tile_free(g_resource->wal_bmp);
/*        DeleteObject(g_resource->wal_bmp);*/
        free(g_resource);
        g_resource = NULL;
    }
}

#endif /* NH2K_EXTENDS */
