#pragma once
///@file

#ifdef _WIN32
#  include <errhandlingapi.h>

#  include "nix/util/error.hh"

namespace nix::windows {

/**
 * Windows Error type.
 *
 * Unless you need to catch a specific error number, don't catch this in
 * portable code. Catch `SystemError` instead.
 */
class WinError : public SystemError
{
public:
    DWORD lastError;

    /**
     * Construct using the explicitly-provided error number.
     * `FormatMessageA` will be used to try to add additional
     * information to the message.
     */
    template<typename... Args>
    WinError(DWORD lastError, const Args &... args)
        : SystemError("")
        , lastError(lastError)
    {
        auto hf = HintFmt(args...);
        err.msg = HintFmt("%1%: %2%", Uncolored(hf.str()), renderError(lastError));
    }

    /**
     * Construct using `GetLastError()` and the ambient "last error".
     *
     * Be sure to not perform another last-error-modifying operation
     * before calling this constructor!
     */
    template<typename... Args>
    WinError(const Args &... args)
        : WinError(GetLastError(), args...)
    {
    }

private:

    std::string renderError(DWORD lastError);
};

} // namespace nix::windows
#endif
