// Written in the D programming language.

/**
 * Convert Win32 error code to string.
 *
 * Copyright: Copyright The D Language Foundation" 2006 - 2013.
 * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
 * Authors:   $(HTTP digitalmars.com, Walter Bright)
 * Credits:   Based on code written by Regan Heath
 */
/*          Copyright The D Language Foundation" 2006 - 2013.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
module std.windows.syserror;
import std.traits : isSomeString;

version (StdDdoc)
{
    private
    {
        alias DWORD = uint;
        enum LANG_NEUTRAL = 0, SUBLANG_DEFAULT = 1;
    }

    /** Query the text for a Windows error code, as returned by
        $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360.aspx,
        `GetLastError`), as a D string.
     */
    string sysErrorString(
        DWORD errCode,
        // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) is the user's default language
        int langId = LANG_NEUTRAL,
        int subLangId = SUBLANG_DEFAULT) @trusted;

    /*********************
       Thrown if errors that set
       $(LINK2 http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360.aspx,
       `GetLastError`) occur.
     */
    class WindowsException : Exception
    {
        private alias DWORD = int;
        final @property DWORD code(); /// `GetLastError`'s return value.
        this(DWORD code, string str=null, string file = null, size_t line = 0) @trusted;
    }

    /++
        If `!!value` is true, `value` is returned. Otherwise,
        $(D new WindowsException(GetLastError(), msg)) is thrown.
        `WindowsException` assumes that the last operation set
        `GetLastError()` appropriately.

        Example:
        --------------------
        wenforce(DeleteFileA("junk.tmp"), "DeleteFile failed");
        --------------------
     +/
    T wenforce(T, S)(T value, lazy S msg = null,
        string file = __FILE__, size_t line = __LINE__) @safe
    if (isSomeString!S);
}
else:

version (Windows):

import core.sys.windows.winbase, core.sys.windows.winnt;
import std.array : appender;
import std.conv : to;
import std.format.write : formattedWrite;
import std.windows.charset;

string sysErrorString(
    DWORD errCode,
    // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) is the user's default language
    int langId = LANG_NEUTRAL,
    int subLangId = SUBLANG_DEFAULT) @trusted
{
    auto buf = appender!string();

    if (!putSysError(errCode, buf, MAKELANGID(langId, subLangId)))
    {
        throw new Exception(
            "failed getting error string for WinAPI error code: " ~
            sysErrorString(GetLastError()));
    }

    return buf.data;
}

bool putSysError(Writer)(DWORD code, Writer w, /*WORD*/int langId = 0)
{
    wchar *lpMsgBuf = null;
    auto res = FormatMessageW(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        null,
        code,
        langId,
        cast(LPWSTR)&lpMsgBuf,
        0,
        null);
    scope(exit) if (lpMsgBuf) LocalFree(lpMsgBuf);

    if (lpMsgBuf)
    {
        import std.string : strip;
        w.put(lpMsgBuf[0 .. res].strip());
        return true;
    }
    else
        return false;
}


class WindowsException : Exception
{
    import core.sys.windows.windef : DWORD;

    final @property DWORD code() { return _code; } /// `GetLastError`'s return value.
    private DWORD _code;

    this(DWORD code, string str=null, string file = null, size_t line = 0) @trusted
    {
        _code = code;

        auto buf = appender!string();

        if (str != null)
        {
            buf.put(str);
            if (code)
                buf.put(": ");
        }

        if (code)
        {
            auto success = putSysError(code, buf);
            formattedWrite(buf, success ? " (error %d)" : "Error %d", code);
        }

        super(buf.data, file, line);
    }
}


T wenforce(T, S)(T value, lazy S msg = null,
string file = __FILE__, size_t line = __LINE__)
if (isSomeString!S)
{
    if (!value)
        throw new WindowsException(GetLastError(), to!string(msg), file, line);
    return value;
}

T wenforce(T)(T condition, const(char)[] name, const(wchar)* namez, string file = __FILE__, size_t line = __LINE__)
{
    if (condition)
        return condition;
    string names;
    if (!name)
    {
        static string trustedToString(const(wchar)* stringz) @trusted
        {
            import core.stdc.wchar_ : wcslen;
            import std.conv : to;
            auto len = wcslen(stringz);
            return to!string(stringz[0 .. len]);
        }

        names = trustedToString(namez);
    }
    else
        names = to!string(name);
    throw new WindowsException(GetLastError(), names, file, line);
}

version (Windows)
@system unittest
{
    import std.algorithm.searching : startsWith, endsWith;
    import std.exception;
    import std.string;

    auto e = collectException!WindowsException(
        DeleteFileA("unexisting.txt").wenforce("DeleteFile")
    );
    assert(e.code == ERROR_FILE_NOT_FOUND);
    assert(e.msg.startsWith("DeleteFile: "));
    // can't test the entire message, as it depends on Windows locale
    assert(e.msg.endsWith(" (error 2)"));

    // Test code zero
    e = new WindowsException(0);
    assert(e.msg == "");

    e = new WindowsException(0, "Test");
    assert(e.msg == "Test");
}
