/*
 * DirectX 8 error routines
 *
 * Copyright 2004 Robert Reif
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * TODO:
 *      Add error codes for D3D8, D3DX8, DDRAW, DPLAY8, DMUSIC, DINPUT and DSHOW.
 *      Sort list for faster lookup.
 */

#include <stdarg.h>
#include <stdio.h>

#define COM_NO_WINDOWS_H
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"

#include "mmsystem.h"
#include "dsound.h"

#include "dxerr8.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(dxerr);

typedef struct {
    HRESULT      hr;
    const CHAR*  resultA;
    const WCHAR* resultW;
    const CHAR*  descriptionA;
    const WCHAR* descriptionW;
} error_info;

#include "errors.h"

const char * WINAPI DXGetErrorString8A(HRESULT hr)
{
    unsigned int i;
    TRACE("(0x%08lx)\n", hr);

    for (i = 0; i < sizeof(info)/sizeof(info[0]); i++) {
        if (hr == info[i].hr)
            return info[i].resultA;
    }

    return "Unknown";
}

const WCHAR * WINAPI DXGetErrorString8W(HRESULT hr)
{
    static const WCHAR unknown[] = { 'U', 'n', 'k', 'n', 'o', 'w', 'n', 0 };
    unsigned int i;
    TRACE("(0x%08lx)\n", hr);

    for (i = 0; i < sizeof(info)/sizeof(info[0]); i++) {
        if (hr == info[i].hr) {
            return info[i].resultW;
        }
    }

    return unknown;
}

const char * WINAPI DXGetErrorDescription8A(HRESULT hr)
{
    unsigned int i;
    TRACE("(0x%08lx)\n", hr);

    for (i = 0; i < sizeof(info)/sizeof(info[0]); i++) {
        if (hr == info[i].hr)
            return info[i].descriptionA;
    }

    return "n/a";
}

const WCHAR * WINAPI DXGetErrorDescription8W(HRESULT hr)
{
    static const WCHAR na[] = { 'n', '/', 'a', 0 };
    unsigned int i;
    TRACE("(0x%08lx)\n", hr);

    for (i = 0; i < sizeof(info)/sizeof(info[0]); i++) {
        if (hr == info[i].hr) {
            return info[i].descriptionW;
        }
    }

    return na;
}

HRESULT WINAPI DXTraceA(const char* strFile, DWORD dwLine, HRESULT hr, const char*  strMsg, BOOL bPopMsgBox)
{
    char msg[1024];
    TRACE("(%p,%ld,0x%08lx,%p,%d)\n", strFile, dwLine, hr, strMsg, bPopMsgBox);

    if (bPopMsgBox) {
        snprintf(msg, sizeof(msg), "File: %s\nLine: %ld\nError Code: %s (0x%08lx)\nCalling: %s",
            strFile, dwLine, DXGetErrorString8A(hr), hr, strMsg);
        MessageBoxA(0, msg, "Unexpected error encountered", MB_OK|MB_ICONERROR);
    } else {
        snprintf(msg, sizeof(msg), "%s(%ld): %s (hr=%s (0x%08lx))", strFile,
            dwLine, strMsg, DXGetErrorString8A(hr), hr);
        OutputDebugStringA(msg);
    }

    return hr;
}

HRESULT WINAPI DXTraceW(const char* strFile, DWORD dwLine, HRESULT hr, const WCHAR* strMsg, BOOL bPopMsgBox)
{
    WCHAR msg[1024];
    TRACE("(%p,%ld,0x%08lx,%p,%d)\n", strFile, dwLine, hr, strMsg, bPopMsgBox);

    if (bPopMsgBox) {
        static const WCHAR format[] = { 'F','i','l','e',':',' ','%','s','\\','n','L','i','n',
            'e',':',' ','%','l','d','\\','n','E','r','r','o','r',' ','C','o',
            'd','e',':',' ','%','s',' ','(','0','x','%','0','8','l','x',')',
            '\\','n','C','a','l','l','i','n','g',':',' ','%','s',0 };
        static const WCHAR caption[] = { 'U','n','e','x','p','e','c','t','e','d',' ','e','r',
            'r','o','r',' ','e','n','c','o','u','n','t','e','r','e','d',0 };
        /* FIXME: should use wsnprintf */
        wsprintfW(msg, format, strFile, dwLine,
                  DXGetErrorString8W(hr), hr, strMsg);
        MessageBoxW(0, msg, caption, MB_OK|MB_ICONERROR);
    } else {
        static const WCHAR format[] = { '%','s','(','%','l','d',')',':',' ','%','s',' ','(',
            'h','r','=','%','s',' ','(','0','x','%','0','8','l','x',')',')',' ',
            0 };
        /* FIXME: should use wsnprintf */
        wsprintfW(msg, format, strFile, dwLine, strMsg,
                  DXGetErrorString8W(hr), hr);
        OutputDebugStringW(msg);
    }

    return hr;
}
