from ctypes import *
from comtypes import GUID, IUnknown, COMMETHOD, HRESULT, dispid
from comtypes.automation import VARIANT, tagEXCEPINFO

# XXX Replace by canonical solution!!!
POINTER_c_wchar = c_wchar_p

class IErrorLog(IUnknown):
    _iid_ = GUID('{3127CA40-446E-11CE-8135-00AA004BB851}')
    _idlflags_ = []
    _methods_ = [
        COMMETHOD([], HRESULT, 'AddError',
                  ( ['in'], POINTER_c_wchar, 'pszPropName' ),
                  ( ['in'], POINTER(tagEXCEPINFO), 'pExcepInfo' )),
        ]

class IPersist(IUnknown):
    _iid_ = GUID('{0000010C-0000-0000-C000-000000000046}')
    _idlflags_ = []
    _methods_ = [
        COMMETHOD([], HRESULT, 'GetClassID',
                  ( ['out'], POINTER(GUID), 'pClassID' )),
        ]

class IPropertyBag(IUnknown):
    _iid_ = GUID('{55272A00-42CB-11CE-8135-00AA004BB851}')
    _idlflags_ = []
    _methods_ = [
        COMMETHOD([], HRESULT, 'Read',
                  ( ['in'], POINTER_c_wchar, 'pszPropName' ),
                  ( ['out'], POINTER(VARIANT), 'pVar' ),
                  ( ['in'], POINTER(IErrorLog), 'pErrorLog' )),
        COMMETHOD([], HRESULT, 'Write',
                  ( ['in'], POINTER_c_wchar, 'pszPropName' ),
                  ( ['in'], POINTER(VARIANT), 'pVar' )),
        ]

class IPersistPropertyBag(IPersist):
    _iid_ = GUID('{37D84F60-42CB-11CE-8135-00AA004BB851}')
    _idlflags_ = []
    _methods_ = [
        COMMETHOD([], HRESULT, 'InitNew'),
        COMMETHOD([], HRESULT, 'Load',
                  ( ['in'], POINTER(IPropertyBag), 'pPropBag' ),
                  ( ['in'], POINTER(IErrorLog), 'pErrorLog' )),
        COMMETHOD([], HRESULT, 'Save',
                  ( ['in'], POINTER(IPropertyBag), 'pPropBag' ),
                  ( ['in'], c_int, 'fClearDirty' ),
                  ( ['in'], c_int, 'fSaveAllProperties' )),
        ]


CLIPFORMAT = c_ulong # Hm, is that correct?

PROPBAG2_TYPE_UNDEFINED = 0
PROPBAG2_TYPE_DATA = 1
PROPBAG2_TYPE_URL = 2
PROPBAG2_TYPE_OBJECT = 3
PROPBAG2_TYPE_STREAM = 4
PROPBAG2_TYPE_STORAGE = 5
PROPBAG2_TYPE_MONIKER = 6

class tagPROPBAG2(Structure):
    _fields_ = [
        ('dwType', c_ulong),
        ('vt', c_ushort),
        ('cfType', CLIPFORMAT),
        ('dwHint', c_ulong),
        ('pstrName', POINTER_c_wchar),
        ('clsid', GUID),
        ]
assert sizeof(tagPROPBAG2) == 36, sizeof(tagPROPBAG2)
assert alignment(tagPROPBAG2) == 4, alignment(tagPROPBAG2)

class IPropertyBag2(IUnknown):
    _iid_ = GUID('{22F55882-280B-11D0-A8A9-00A0C90C2004}')
    _idlflags_ = []
    _methods_ = [
        COMMETHOD([], HRESULT, 'Read',
                  ( ['in'], c_ulong, 'cProperties' ),
                  ( ['in'], POINTER(tagPROPBAG2), 'pPropBag' ),
                  ( ['in'], POINTER(IErrorLog), 'pErrLog' ),
                  ( ['out'], POINTER(VARIANT), 'pvarValue' ),
                  ( ['out'], POINTER(HRESULT), 'phrError' )),
        COMMETHOD([], HRESULT, 'Write',
                  ( ['in'], c_ulong, 'cProperties' ),
                  ( ['in'], POINTER(tagPROPBAG2), 'pPropBag' ),
                  ( ['in'], POINTER(VARIANT), 'pvarValue' )),
        COMMETHOD([], HRESULT, 'CountProperties',
                  ( ['out'], POINTER(c_ulong), 'pcProperties' )),
        COMMETHOD([], HRESULT, 'GetPropertyInfo',
                  ( ['in'], c_ulong, 'iProperty' ),
                  ( ['in'], c_ulong, 'cProperties' ),
                  ( ['out'], POINTER(tagPROPBAG2), 'pPropBag' ),
                  ( ['out'], POINTER(c_ulong), 'pcProperties' )),
        COMMETHOD([], HRESULT, 'LoadObject',
                  ( ['in'], POINTER_c_wchar, 'pstrName' ),
                  ( ['in'], c_ulong, 'dwHint' ),
                  ( ['in'], POINTER(IUnknown), 'punkObject' ),
                  ( ['in'], POINTER(IErrorLog), 'pErrLog' )),
        ]

class IPersistPropertyBag2(IPersist):
    _iid_ = GUID('{22F55881-280B-11D0-A8A9-00A0C90C2004}')
    _idlflags_ = []
    _methods_ = [
        COMMETHOD([], HRESULT, 'InitNew'),
        COMMETHOD([], HRESULT, 'Load',
                  ( ['in'], POINTER(IPropertyBag2), 'pPropBag' ),
                  ( ['in'], POINTER(IErrorLog), 'pErrLog' )),
        COMMETHOD([], HRESULT, 'Save',
                  ( ['in'], POINTER(IPropertyBag2), 'pPropBag' ),
                  ( ['in'], c_int, 'fClearDirty' ),
                  ( ['in'], c_int, 'fSaveAllProperties' )),
        COMMETHOD([], HRESULT, 'IsDirty'),
        ]

