from PyQt4.QtCore import QTimer, Qt, SIGNAL
from PyQt4.QtGui import QTextBrowser, QVBoxLayout, QListWidget, qApp, QListWidgetItem, QWidget


class PopupWidget(QWidget):


    def __init__(self, textedit):
        flags = Qt.ToolTip
        flags = Qt.Window | Qt.FramelessWindowHint | \
                Qt.CustomizeWindowHint | Qt.X11BypassWindowManagerHint
        QWidget.__init__(self, None, flags)
        self.textedit = textedit
        self.vlayout = QVBoxLayout(self)
        self.vlayout.setContentsMargins(0, 0, 0, 0)
        self.init_popup()
        self.show()
        self.hide()
        self.active = False


    def show(self, timeout=0, above=False):
        self.cursor_start_col = self.textedit.textCursor().columnNumber()
        desktop = qApp.desktop()
        screen = desktop.screen(desktop.screenNumber(self))
        screen_width = screen.width()
        screen_height = screen.height()
        win_width = self.width()
        win_height = self.height()
        cursorRect = self.textedit.cursorRect()
        if above:
            pos = self.textedit.mapToGlobal(cursorRect.topLeft())
            pos.setY(pos.y() - win_height)
        else:
            pos = self.textedit.mapToGlobal(cursorRect.bottomLeft())
        if pos.y() < 0:
            pos = self.textedit.mapToGlobal(cursorRect.bottomLeft())
        if pos.y() + win_height > screen_height:
            pos = self.textedit.mapToGlobal(cursorRect.topLeft())
            pos.setY(pos.y() - win_height)
        if pos.x() + win_width > screen_width:
            pos.setX(screen_width - win_width)

        self.move(pos)
        QWidget.show(self)
        self.active = True
        if timeout:
            QTimer.singleShot(timeout * 1000, self.hide)


    def hide(self):
        self.active = False
        QWidget.hide(self)






class CallTip(PopupWidget):


    def init_popup(self):
        self.browser = QTextBrowser(self)
        self.layout().addWidget(self.browser)




class AutoCompleteItem(QListWidgetItem):

    def __init__(self, item):
        QListWidgetItem.__init__(self)
        value = item.name
        self.setText(value)
        self.value = value
        self.kind = item.kind



class AutoComplete(PopupWidget):


    def init_popup(self):
        self.list = QListWidget(self)
        self.connect(self.list,
                     SIGNAL("itemClicked(QListWidgetItem*)"),
                     self.insertItem)
        self.layout().addWidget(self.list)
        self.items = []


    def insertItem(self, item):
        self.insert()


    def insert(self):
        completion = self.items[self.list.currentRow()].value
        cursor = self.textedit.textCursor()
        col = cursor.columnNumber()
        line = unicode(cursor.block().text())
        i = self.cursor_start_col
        while i > 0:
            #print `line[i:col]`
            if completion.startswith(line[i:col]):
                #print "break"
                break
            i -= 1
        #print col,i
        cursor.insertText(completion[col-i:])
        self.hide()


    def setItems(self, proposals):
        proposals = sorted(proposals, cmp=lambda p1,p2:cmp(p1.name,p2.name))
        del self.items[:]
        self.list.clear()
        for entry in proposals:
            i = AutoCompleteItem(entry)
            self.list.addItem(i)
            self.items.append(i)


    def keyPressEvent(self, event):
        self.list.keyPressEvent(event)
        key = event.key()
        text = event.text()
        if key in [Qt.Key_Right, Qt.Key_Enter, Qt.Key_Return]:
            text = ""
        cursor = self.textedit.textCursor()
        line = unicode(cursor.block().text())
        col = cursor.columnNumber()
        prefix = line[self.cursor_start_col:col] + unicode(text)

        found = False
        for row, item in enumerate(self.items):
            if item.value.startswith(prefix):
                current = self.items[self.list.currentRow()].value
                if not current.startswith(prefix):
                    self.list.setCurrentRow(row)
                found = True
                break
        if not found:
            self.hide()
            return

        if key in [Qt.Key_Up, Qt.Key_Down, Qt.Key_PageUp, Qt.Key_PageDown]:
            return True
        elif key in [Qt.Key_Tab, Qt.Key_Right, Qt.Key_Enter, Qt.Key_Return]:
            self.insert()
            return True
        elif not text:
            self.hide()



