import frame as fm
from settings import ConnectReturn as CR
from settings import TYPE
import socket, select
from threading import Timer, Thread
from frame import Frame

class Broker(Frame):
    def __init__(self, host = "127.0.0.1", port = 8888):
        super(Broker, self).__init__()
        self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.serv.bind((host, port))
        self.host = host
        self.port = port
        self.clients = {}
        self.topics = {}
        self.wills = {}
        self.clientSubscribe = {}
        # NOTICE: keys of topics and clientSubscribe should be synchronized

    def worker(self, con, addr):
        data = "dummy"
        while len(data):
            data = con.recv(1 << 16)
            self.parseFrame(data, con, addr)
            if self.clients.has_key(addr):
                self.clients[addr].restartTimer()

    def runServer(self):
        self.serv.listen(1)
        threadNumber = 0
        self.threads = []
        while True:
            con, addr = self.serv.accept()
            thread = Thread(target = self.worker, args = (con, addr, ))
            thread.start()

    def setClient(self, con, addr, cliID, name, passwd, will, keepAlive, clean):
        self.clients[addr] = Client(self, addr, con, cliID, name,
                                    passwd, will, keepAlive, clean)

    def setTopic(self, addr, topicQoS, messageID):
        self.clients[addr].subscribe.append(topicQoS)

        if self.clientSubscribe.has_key(topicQoS[0]):
            self.clientSubscribe[topicQoS[0]].append([addr, topicQoS[1]])
            # this is 'retain'
            if self.topics[topicQoS[0]]:
                frame = self.makeFrame(TYPE.PUBLISH, 0, topicOoS[1], 1, topic = topicQoS[0],
                                     message = self.topics[topicQoS[0]], messageID = messageID)
                self.clients[addr].sock.send(frame)
        else:
            self.clientSubscribe[topicQoS[0]] = [[addr, topicQoS[1]]]

    def unsetWill(self):
        #when
        pass

    def sendWill(self, frame):
        pass # send willFrame to clients ?

    def unsetTopic(self, addr, topic):
        # not cool
        self.clients[addr].unsetTopic(topic)
        self.clientSubscribe[topic].remove(self.clientSubscribe[topic][[a[0] for a in self.clientSubscribe[topic]].index(addr)])

    def disconnect(self, addr):
        # when get DISCONNECT packet from client
        self.clients[addr].sock.close()
        if self.clients[addr].clean:
            # TODO: correct ?
            self.clients.pop(addr)
        print "disconnect"

    def publish(self, topic, message, messageID = 1, retain = 0):
        if self.topics.has_key(topic):
            for client in self.topics[topic]:
                frame = self.makeFrame(TYPE.PUBLISH, 0, client[1], 0, topic = topic,
                                     message = message, messageID = messageID)
                self.clients[client[0]].send(frame) # TODO: send function should be unified
        else:
            self.topics[topic] = ""

        if retain:
            self.topics[topic] = message

class Client():
    def __init__(self, server, addr, sock, cliID = "", name = "",
                 passwd = "", will = {}, keepAlive = 2, clean = 1):
        self.server = server
        self.addr = addr
        self.sock = sock
        if not cliID:
            cliID = "random" # TODO: cliID should be determined in here if no cliID was delivered.
        self.cliID = cliID
        self.name = name
        self.passwd = passwd
        self.will = will
        self.keepAlive = keepAlive
        self.timer = Timer(keepAlive * 1.5, self.disconnect)
        self.subscribe = []
        self.clean = clean

    def sendWill(self, frame):
        self.server.sendWill(frame)

    def disconnect(self):
        # when ping packet didn't came within the keepAlive * 1.5 sec
        frame = self.makeFrame(TYPE.PUBLISH, 0, self.will["QoS"], self.will["retain"],
                             topic = self.will["topic"], message = self.will["message"], messageID = 1)
        self.sendWill(frame)
        frame = self.makeFrame(TYPE.DISCONNECT, 0, 0, 0)
        self.send(frame)
        self.sock.close()
        self.server.clients.pop(self.addr)

    def unsetTopic(self, topic):
        self.subscribe.remove(self.subscribe[[t[0] for t in self.subscribe].index(topic)])

    def send(self, frame):
        self.sock.send(frame)

    def restartTimer(self):
        self.timer.cancel()
        self.timer = Timer(self.keepAlive * 1.5, self.disconnect)
        self.timer.start()

@@ -1484,31 +1484,22 @@
 if self.
-clientSubscribe
+topics
 .has_key
@@ -1515,70 +1515,25 @@
 %5B0%5D)
-:%0A            self.clientSubscribe%5BtopicQoS%5B0%5D%5D.append(%5Baddr, 
+ and self.topics%5B
 topi
@@ -1541,12 +1541,12 @@
 QoS%5B
-1%5D%5D)
+0%5D%5D:
 %0A   
@@ -1577,53 +1577,8 @@
 in'%0A
-            if self.topics%5BtopicQoS%5B0%5D%5D:%0A    
     
@@ -1630,17 +1630,17 @@
 0, topic
-O
+Q
 oS%5B1%5D, 1
@@ -1662,18 +1662,16 @@
 QoS%5B0%5D,%0A
-  
         
@@ -1760,36 +1760,32 @@
 ID)%0A            
-    
 self.clients%5Badd
@@ -1795,32 +1795,161 @@
 sock.send(frame)
+%0A%0A        if self.clientSubscribe.has_key(topicQoS%5B0%5D):%0A            self.clientSubscribe%5BtopicQoS%5B0%5D%5D.append(%5Baddr, topicQoS%5B1%5D%5D)
 %0A        else:%0A 
@@ -3934,32 +3934,39 @@
    frame = self.
+server.
 makeFrame(TYPE.P
@@ -4161,32 +4161,39 @@
    frame = self.
+server.
 makeFrame(TYPE.D

fix several bugs