import win32con
import sys
from ctypes import *
import time


import win32con

from ctypes import *
from ctypes.wintypes import *
from comtypes import IUnknown
from comtypes.automation import IDispatch, VARIANT
from comtypes.client import wrap, GetModule

#from win32com.client import *
#cast = gencache.GetModuleForProgID('htmlfile')

if not hasattr(sys, 'frozen'):
    GetModule('atl.dll')
    GetModule('shdocvw.dll')

kernel32 = windll.kernel32
user32 = windll.user32
atl = windll.atl                  # If this fails, you need atl.dll

import win32con
from ctypes import *
from comtypes import IUnknown
from comtypes.automation import VARIANT
from comtypes.client import GetEvents
from comtypes.gen import SHDocVw
from comtypes.gen import MSHTML

kernel32 = windll.kernel32
user32 = windll.user32

WNDPROC = WINFUNCTYPE(c_long, c_int, c_uint, c_int, c_int)

class WNDCLASS(Structure):
    _fields_ = [('style', c_uint),
                ('lpfnWndProc', WNDPROC),
                ('cbClsExtra', c_int),
                ('cbWndExtra', c_int),
                ('hInstance', c_int),
                ('hIcon', c_int),
                ('hCursor', c_int),
                ('hbrBackground', c_int),
                ('lpszMenuName', c_char_p),
                ('lpszClassName', c_char_p)]

class RECT(Structure):
    _fields_ = [('left', c_long),
                ('top', c_long),
                ('right', c_long),
                ('bottom', c_long)]

class PAINTSTRUCT(Structure):
    _fields_ = [('hdc', c_int),
                ('fErase', c_int),
                ('rcPaint', RECT),
                ('fRestore', c_int),
                ('fIncUpdate', c_int),
                ('rgbReserved', c_char * 32)]

class POINT(Structure):
    _fields_ = [('x', c_long),
                ('y', c_long)]
    
class MSG(Structure):
    _fields_ = [('hwnd', c_int),
                ('message', c_uint),
                ('wParam', c_int),
                ('lParam', c_int),
                ('time', c_int),
                ('pt', POINT)]

def ErrorIfZero(handle):
    if handle == 0:
        raise WinError
    else:
        return handle

def _createDiv(doc):
    div = doc.createElement('div')
    style = div.style
    style2 = cast.IHTMLStyle2(style)
    style3 = cast.IHTMLStyle3(style)
    style2.position = 'absolute'
    style.top = 0
    style.left = 0
    style.overflow = 'scroll'
    style2.overflowX = 'hidden'
    style.width = 300
    style.height = 100
    style3.scrollbarBaseColor = '#3366CC'
    style.borderBottom = '2px solid black'
    style3.scrollbarHighlightColor = '#99CCFF'
    style3.scrollbarArrowColor = 'white'
    div.innerHTML = 'Hello'
    return div

#b = Dispatch('InternetExplorer.Application')
#b.Navigate('about:<h1 id=header>Hello</h1><iframe id=frm src="about:"></iframe>')
#b.Visible = 1
#doc1 = cast.IHTMLDocument2(b.Document)
#header = doc1.all.item('header')
#frm = doc1.all.item('frm')
#frm2 = doc1.frames('frm')
#doc2 = cast.IHTMLDocument2(frm2.document)
#div = doc2.createElement('div')
#cast.DispHTMLBody(doc2.body).appendChild(div)

#popup = cast.DispHTMLWindow2(doc1.parentWindow).createPopup()
#doc3 = cast.IHTMLDocument2(popup.document)
#body = cast.DispHTMLBody(doc3.body)
#div = _createDiv()

class EventSink(object):
    # some DWebBrowserEvents
    def OnVisible(self, this, *args):
        print "OnVisible", args

    def BeforeNavigate(self, this, *args):
        print "BeforeNavigate", args

    def NavigateComplete(self, this, *args):
        if self._loaded:
            return
        self._loaded = True
        print "NavigateComplete", this, args
        #pDoc = wrap(this)
        #print dir(pDoc)
        #sys.stdout.flush()
        return
        #div = _createDiv(doc2)
        #print div, div.document
        #doc2.body.appendChild(div)
        #cast.DispHTMLBody(doc2.body).appendChild(div)


    # some DWebBrowserEvents2
    def BeforeNavigate2(self, this, *args):
        print "BeforeNavigate2", args

    def NavigateComplete2(self, this, *args):
        print "NavigateComplete2", args

    def DocumentComplete(self, this, *args):
        self.valid_doc = time.time() + 1
        print "DocumentComplete", args

    def NewWindow2(self, this, *args):
        print "NewWindow2", args
        return
        v = cast(args[1]._.c_void_p, POINTER(VARIANT))[0]
        v.value = True

    def NewWindow3(self, this, *args):
        print "NewWindow3", args
        return
        v = cast(args[1]._.c_void_p, POINTER(VARIANT))[0]
        v.value = True

class Browser(EventSink):
    def __init__(self, url):
        EventSink.__init__(self)
        self._loaded = False
        self.valid_doc = False
        CreateWindowEx = windll.user32.CreateWindowExA
        CreateWindowEx.argtypes = [c_int, c_char_p, c_char_p, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int]
        CreateWindowEx.restype = ErrorIfZero

        # Create an instance of IE via AtlAxWin.
        atl.AtlAxWinInit()
        hInstance = kernel32.GetModuleHandleA(None)

        hwnd = CreateWindowEx(0,
                              "AtlAxWin",
                              "Python Window",
                              win32con.WS_OVERLAPPEDWINDOW |
                              win32con.WS_VISIBLE | 
                              win32con.WS_HSCROLL | win32con.WS_VSCROLL,
                              win32con.CW_USEDEFAULT,
                              win32con.CW_USEDEFAULT,
                              win32con.CW_USEDEFAULT,
                              win32con.CW_USEDEFAULT,
                              win32con.NULL,
                              win32con.NULL,
                              hInstance,
                              win32con.NULL)

        # Get the IWebBrowser2 interface for the IE control.
        self.pBrowserUnk = POINTER(IUnknown)()
        atl.AtlAxGetControl(hwnd, byref(self.pBrowserUnk))
        # the wrap call querys for the default interface
        self.pBrowser = wrap(self.pBrowserUnk)
        self.pBrowser.RegisterAsBrowser = True
        self.pBrowser.AddRef()

        #self.conn = GetEvents(self.pBrowser, sink=self,
        #                interface=SHDocVw.DWebBrowserEvents2)

        v = byref(VARIANT())
        self.pBrowser.Navigate(url, v, v, v, v)

        # Show Window
        windll.user32.ShowWindow(c_int(hwnd), c_int(win32con.SW_SHOWNORMAL))
        windll.user32.UpdateWindow(c_int(hwnd))

def MainWin():

    #b = Browser("about:blank")
    #b = Browser("http://google.co.uk")
    b = Browser("http://pyjs.org")

    # Pump Messages
    msg = MSG()
    pMsg = pointer(msg)
    NULL = c_int(win32con.NULL)
    
    while windll.user32.GetMessageA( pMsg, NULL, 0, 0) != 0:

        if b.valid_doc:
            print b.valid_doc, time.time()
            if b.valid_doc < time.time():
                b.valid_doc = 0
                #pDoc = wrap(args[0])
                #print pDoc
                #print dir(pDoc)
                #print pDoc.Width
                #doc2 = pDoc.QueryInterface(SHDocVw.IWebBrowser2)
                #print doc2
                #doc2 = pDoc.QueryInterface(MSHTML.IHTMLDocument2)
                #d = doc2.Document
                #iw = iw.QueryInterface(MSHTML.IHTMLDocument2)
                print dir(b.pBrowser)
                sys.stdout.flush()
        if hasattr(b.pBrowser, "Document"):
            print "doc", b.pBrowser.Document
        windll.user32.TranslateMessage(pMsg)
        windll.user32.DispatchMessageA(pMsg)

        print msg.message
        #if msg.message == 161: # win32con.WM_DESTROY:
        #    windll.user32.PostQuitMessage(0)


    return msg.wParam
    
if __name__=='__main__':
    sys.exit(MainWin())

