import lib
import time
import socket
import logging as log

class Server(object):

    def __init__(self, config):
        self.host = '0.0.0.0'
        self.port = int(config.get("Comm", "port"))
        self.finish = 0

        addr = (self.host, self.port)
        log.debug("Setup TCP server at %s:%s" % addr)
        self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.tcp.bind(addr)
        self.tcp.listen(1)
        log.info("TCP server listening at %s:%s (sock=%d)" %
                 (self.host, self.port, self.tcp.fileno()))

    def getMsg(self):
        bytes = []
        try:
            while 1:
                c = self.con.recv(1)
                bytes.append(c)
                if not c or c == "\n":
                    break
        except Exception, e:
            log.error("Error reading message from client: %s" % e)
            return None

        if not bytes or bytes[-1] != "\n":
            msg = "".join(bytes)
            log.error("Invalid message from client: %r" % msg)
            return None

        # remove \n and \r
        bytes.pop()
        if bytes[-1] == "\r":
            bytes.pop()

        msg = "".join(bytes)
        log.debug("RECV: %r" % msg)
        return msg

    def sendMsg(self, msg):
        log.debug("SEND: %r" % msg)
        self.con.send(msg + "\n")

    def sendOk(self, payload=None):
        self.sendMsg("OK %d" % bool(payload is not None))
        if payload is not None:
            if not isinstance(payload, (tuple, list)):
                payload = (payload,)
            for e in payload:
                self.sendMsg("+%s" % e)
            self.sendMsg(".")

    def sendNotOk(self, reason=""):
        self.sendMsg("NOTOK %r" % reason)

    def getRequest(self):
        log.debug("Wait for client request at %s:%s (sock=%d)" %
                  (self.host, self.port, self.tcp.fileno()))
        self.con, self.client = self.tcp.accept()
        log.info("Incoming request from %s (con=%s)" %
                 (self.client, self.con.fileno()))
        return (self.con, self.client, self.port)

    def disconnect_client(self, connection):
        log.info("Closed request from %s (con=%s)" %
                 (self.client, self.con.fileno()))
        connection.close()

    def stop(self):
        log.debug("Stop")
        self.tcp.close()
