#include "variant.h"

#include <QDebug>
#include "tool.h"

#include <Wbemidl.h>

namespace Win
{

QString QS(const LPCSTR propStr)
{
    return QString::fromStdString(propStr);
}

QString WQS(const LPCWSTR propStr)
{
    return QString::fromStdWString(propStr);
}

VOID Win::dumpProp(const VARIANT &prop, const LPCWSTR propStr)
{
    switch (prop.vt) {
    case VT_EMPTY:
        qDebug() << "VT_EMPTY" << WQS(propStr) << ":" << "Empry Value";
        break;
    case VT_NULL:
        qDebug() << "VT_NULL" << WQS(propStr) << ":" << "Sql Null Value";
        break;
    case VT_I2:
    case VT_I4:
        qDebug() << "Property  VT_I4" << WQS(propStr) << ":" << prop.intVal << Tool::qHexStr1(prop.uintVal);
        break;
    case VT_R4:
    case VT_R8:
        qDebug() << "VT_R8" << WQS(propStr) << ":" << prop.dblVal;
        break;
    // VT_CY = 6,
    // VT_DATE   = 7,
    case VT_BSTR:
        qDebug() << "VT_BSTR" << WQS(propStr) << ":" << WQS(prop.bstrVal);
        break;
    // VT_DISPATCH   = 9,
    // VT_ERROR  = 10,
    // VT_BOOL   = 11,
    case VT_BOOL:
        qDebug() << "VT_BOOL" << WQS(propStr) << ":" << prop.boolVal;
        break;
    // VT_VARIANT    = 12,
    case VT_UNKNOWN:
        qDebug() << "VT_UNKNOWN" << WQS(propStr) << ":" << prop.ppunkVal;
        break;
    // VT_DECIMAL    = 14,
    // VT_I1 = 16,
    // VT_UI1    = 17,
    // VT_UI2    = 18,
    // VT_UI4    = 19,
    // VT_I8 = 20,
    // VT_UI8    = 21,
    // VT_INT    = 22,
    // VT_UINT   = 23,
    // VT_VOID   = 24,
    // VT_HRESULT    = 25,
    // VT_PTR    = 26,
    // VT_SAFEARRAY  = 27,
    // VT_CARRAY = 28,
    // VT_USERDEFINED    = 29,
    // VT_LPSTR  = 30,
    // VT_LPWSTR = 31,
    // VT_RECORD = 36,
    // VT_INT_PTR    = 37,
    // VT_UINT_PTR   = 38,
    // VT_FILETIME   = 64,
    // VT_BLOB   = 65,
    // VT_STREAM = 66,
    // VT_STORAGE    = 67,
    // VT_STREAMED_OBJECT    = 68,
    // VT_STORED_OBJECT  = 69,
    // VT_BLOB_OBJECT    = 70,
    // VT_CF = 71,
    case VT_CLSID:
        //        OLECHAR *bstrGuid;
        //        ::StringFromCLSID(*prop.puuid, &bstrGuid);
        //        qDebug() << "Property " << WQS(propStr) << ":" << WQS(bstrGuid);
        //        ::CoTaskMemFree(bstrGuid);

        break;
    // VT_VERSIONED_STREAM   = 73,
    // VT_BSTR_BLOB  = 0xfff,
    // VT_VECTOR = 0x1000,
    // VT_ARRAY  = 0x2000,
    // VT_BYREF  = 0x4000,
    // VT_RESERVED   = 0x8000,
    // VT_ILLEGAL    = 0xffff,
    // VT_ILLEGALMASKED  = 0xfff,
    // VT_TYPEMASK   = 0xfff
    default:
        qDebug() << "Property " << WQS(propStr) << "Type:" << prop.vt;
        break;
    }
}

QVariant qVariant(const VARIANT &prop)
{
    QVariant value;
    switch (prop.vt) {
    case VT_EMPTY:
        break;
    case VT_NULL:
        break;
    case VT_I2:
    case VT_I4:
        value = QVariant(prop.intVal);
        break;
    case VT_R4:
    case VT_R8:
        value = QVariant(prop.dblVal);
        break;
    // VT_CY = 6,
    // VT_DATE   = 7,
    case VT_BSTR:
        value = QVariant(WQS(prop.bstrVal));
        break;
    // VT_DISPATCH   = 9,
    // VT_ERROR  = 10,
    // VT_BOOL   = 11,
    case VT_BOOL:
        value = QVariant(prop.boolVal == TRUE);
        break;
    // VT_VARIANT    = 12,
    // VT_UNKNOWN    = 13,
    // VT_DECIMAL    = 14,
    // VT_I1 = 16,
    // VT_UI1    = 17,
    // VT_UI2    = 18,
    // VT_UI4    = 19,
    // VT_I8 = 20,
    // VT_UI8    = 21,
    // VT_INT    = 22,
    // VT_UINT   = 23,
    // VT_VOID   = 24,
    // VT_HRESULT    = 25,
    // VT_PTR    = 26,
    // VT_SAFEARRAY  = 27,
    // VT_CARRAY = 28,
    // VT_USERDEFINED    = 29,
    // VT_LPSTR  = 30,
    // VT_LPWSTR = 31,
    // VT_RECORD = 36,
    // VT_INT_PTR    = 37,
    // VT_UINT_PTR   = 38,
    // VT_FILETIME   = 64,
    // VT_BLOB   = 65,
    // VT_STREAM = 66,
    // VT_STORAGE    = 67,
    // VT_STREAMED_OBJECT    = 68,
    // VT_STORED_OBJECT  = 69,
    // VT_BLOB_OBJECT    = 70,
    // VT_CF = 71,
    case VT_CLSID:
        //        OLECHAR *bstrGuid;
        //        ::StringFromCLSID(*prop.puuid, &bstrGuid);
        //        qDebug() << "Property " << WQS(propStr) << ":" << WQS(bstrGuid);
        //        ::CoTaskMemFree(bstrGuid);

        break;
    // VT_VERSIONED_STREAM   = 73,
    // VT_BSTR_BLOB  = 0xfff,
    // VT_VECTOR = 0x1000,
    // VT_ARRAY  = 0x2000,
    // VT_BYREF  = 0x4000,
    // VT_RESERVED   = 0x8000,
    // VT_ILLEGAL    = 0xffff,
    // VT_ILLEGALMASKED  = 0xfff,
    // VT_TYPEMASK   = 0xfff
    default:
        break;
    }
    return value;
}

void dumpWmiObj(IWbemClassObject *pClass)
{
    HRESULT hres = S_OK;

    SAFEARRAY *psaNames = NULL;
    hres = pClass->GetNames(
               NULL,
               WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
               NULL,
               &psaNames);

    if (FAILED(hres)) {
        qDebug() << "GetNames failed" << " Error code = 0x" << Tool::qHexStr1(hres);
        return;
    }

    // Get the number of properties.
    long lLower, lUpper;
    BSTR PropName = NULL;
    SafeArrayGetLBound(psaNames, 1, &lLower);
    SafeArrayGetUBound(psaNames, 1, &lUpper);

    for (long i = lLower; i <= lUpper; i++) {
        // Get this property.
        hres = SafeArrayGetElement(psaNames, &i, &PropName);

        VARIANT vtProp;
        hres = pClass->Get(PropName, 0, &vtProp, 0, 0);
        Win::dumpProp(vtProp, PropName);
        VariantClear(&vtProp);

        SysFreeString(PropName);
    }

    SafeArrayDestroy(psaNames);
}

}
