/*
 * w_misc.c : common routines for core windows
 *
 * Copyright (c) Yukihiko Aoki 1999
 * 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) {
        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 */
    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 *)NEWMEMORY(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 */
        key = "effect_tile";
        if(!GetPrivateProfileString(section, key, "", buf, MAX_PATH, filename)) {
            goto finish_load;
        }
        strcat(info->effect, TILEDIR);
        strcat(info->effect, "\\");
        strcat(info->effect, buf);

        /* load effect description */
        key = "animation";
        if(!GetPrivateProfileString(section, key, "", info->animation, BUFSZ, filename)) {
            goto finish_load;
        }
        /* 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);
            }
            DELMEMORY(info);
            info = NULL;
        }
    }else {
        PrintError("Error: memory allocation");
    }

    return info;
}

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

    info = (WINCONTROL *)NEWMEMORY(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;
        DELMEMORY(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("win32");
            break;
        case MODE_GDI2D:
            result = GDI2D_init(info, callbackProc);
            GDI2D_func(&disp_procs);
            choose_windows("win32");
            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;
}

/***************************************************************************************/
/* Load resources
/***************************************************************************************/
BOOL LoadGlobalResources(HINSTANCE hinst)
{
    BOOL success = TRUE;

    g_resource = (WINRESOURCE *)NEWMEMORY(sizeof(WINRESOURCE));
    if(g_resource) {

        /* Gold */
        g_resource->gld_bmp = Tile_load(
            NULL, "gld.bmp", STB_GOLD_WIDTH, STB_HEIGHT, NULL, NULL);
        if(!g_resource->gld_bmp) {
            g_resource->gld_bmp = Tile_load(
                hinst, "GLD_BMP", STB_GOLD_WIDTH, STB_HEIGHT, NULL, NULL);
        }

        /* Special status */
        g_resource->stt_bmp = Tile_load(
            NULL, "stt.bmp", STB_STAT_WIDTH, STB_HEIGHT, NULL, NULL);
        if(!g_resource->stt_bmp) {
            g_resource->stt_bmp = Tile_load(
                hinst, "STT_BMP", STB_STAT_WIDTH, STB_HEIGHT, NULL, NULL);
        }

        /* Encumbered status */
        g_resource->enc_bmp = Tile_load(NULL, "enc.bmp", STB_ENC_WIDTH, STB_HEIGHT, NULL, NULL);
        if(!g_resource->enc_bmp) {
            g_resource->enc_bmp = Tile_load(
                hinst, "ENC_BMP", STB_ENC_WIDTH, STB_HEIGHT, NULL, NULL);
        }

        /* Hunger status */
        g_resource->hun_bmp = Tile_load(NULL, "hun.bmp", STB_HUN_WIDTH, STB_HEIGHT, NULL, NULL);
        if(!g_resource->hun_bmp) {
            g_resource->hun_bmp = Tile_load(
                hinst, "HUN_BMP", STB_HUN_WIDTH, STB_HEIGHT, NULL, NULL);
        }

        /* Micro map symbol */
        g_resource->sym_bmp = Tile_load(NULL, "sym.bmp", 6, 6, NULL, NULL);
        if(!g_resource->sym_bmp) {
            g_resource->sym_bmp = Tile_load(hinst, "SYM_BMP", 6, 6, 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);

        /* wall */
        g_resource->wal_bmp = LoadImage(
            NULL, "wall.bmp", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);

        return success;
    }
    return FALSE;
}

/***************************************************************************************/
/* Free resources
/***************************************************************************************/
void FreeGlobalResources()
{
    if(g_resource) {
        Tile_free(g_resource->gld_bmp);
        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);
        DeleteObject(g_resource->wal_bmp);
    }
}

#endif /* NH2K_EXTENDS */
