import sys
import time
import struct
import socket
import select
import cPickle as pickle
from urlparse import urlparse


class Timeout(Exception):
    pass


class CantUnpack(Exception):
    pass


# ------------------------------------- Serializers --------------------------


class ISensortResultsSerializer(object):
    def pack(self, data):
        pass

    def unpack(self, data):
        pass


class StructSerializerSend(ISensortResultsSerializer):
    initial_times = 5
    resend_timeout = 60
    HEADERS = 'h'
    DATA = 'd'
    END_OF_HEADERS = '\x00'
    END_OF_SOURCE_ID = '\x00'
    HEADERS_SEPARATOR = '\n'

    def __init__(self):
        self.field_order = None
        self.headers_send_cycles_left = self.initial_times
        self.pack_fmt = None
        self.next_header_send_time = None

    def pack(self, data):
        data = data.copy()

        source_id = data.pop("source_id")
        vals = [int(data.pop("time").value)]

        if self.field_order is None:
            self.field_order = sorted(data.keys())
            self.pack_fmt = "!I" + "I" * len(self.field_order)

        need_resend = False
        if self.next_header_send_time is not None:
            if time.time() > self.next_header_send_time:
                need_resend = True

        if self.headers_send_cycles_left > 0 or need_resend:
            forder = self.HEADERS_SEPARATOR.join(self.field_order)
            flen = struct.pack("!H", len(self.field_order))

            result = (self.HEADERS + source_id +
                      self.END_OF_SOURCE_ID +
                      flen + forder + self.END_OF_HEADERS)

            if self.headers_send_cycles_left > 0:
                self.headers_send_cycles_left -= 1

            self.next_header_send_time = time.time() + self.resend_timeout
        else:
            result = ""

        for name in self.field_order:
            vals.append(int(data[name].value))

        packed_data = self.DATA + source_id
        packed_data += self.END_OF_SOURCE_ID
        packed_data += struct.pack(self.pack_fmt, *vals)

        return result + packed_data


class StructSerializerRecv(ISensortResultsSerializer):
    def __init__(self):
        self.fields = {}
        self.formats = {}

    def unpack(self, data):
        code = data[0]
        source_id, _, packed_data = data[1:].partition(
            StructSerializerSend.END_OF_SOURCE_ID)

        if code == StructSerializerSend.HEADERS:
            # fields order provided
            flen_sz = struct.calcsize("!H")
            flen = struct.unpack("!H", packed_data[:flen_sz])[0]

            headers_data, rest = packed_data[flen_sz:].split(
                StructSerializerSend.END_OF_HEADERS, 1)

            forder = headers_data.split(
                StructSerializerSend.HEADERS_SEPARATOR)

            assert len(forder) == flen, \
                "Wrong len {0} != {1}".format(len(forder), flen)

            if 'source_id' in self.fields:
                assert self.fields[source_id] == ['time'] + forder,\
                    "New field order"
            else:
                self.fields[source_id] = ['time'] + forder
                self.formats[source_id] = "!I" + "I" * flen

            if len(rest) != 0:
                return self.unpack(rest)
            return None
        else:
            assert code == StructSerializerSend.DATA,\
                "Unknown code {0!r}".format(code)

            try:
                fields = self.fields[source_id]
            except KeyError:
                raise CantUnpack("No fields order provided"
                                 " for {0} yet".format(source_id))
            s_format = self.formats[source_id]

            exp_size = struct.calcsize(s_format)
            assert len(packed_data) == exp_size, \
                "Wrong data len {0} != {1}".format(len(packed_data), exp_size)

            vals = struct.unpack(s_format, packed_data)
            res = dict(zip(fields, vals))
            res['source_id'] = source_id
            return res


class PickleSerializer(ISensortResultsSerializer):
    def pack(self, data):
        ndata = {}
        for key, val in data.items():
            if isinstance(val, basestring):
                ndata[key] = val
            else:
                ndata[key] = val.value
        return pickle.dumps(ndata)

    def unpack(self, data):
        return pickle.loads(data)

# ------------------------------------- Transports ---------------------------


class ITransport(object):
    def __init__(self, receiver):
        pass

    def send(self, data):
        pass

    def recv(self, timeout=None):
        pass


class StdoutTransport(ITransport):
    MIN_COL_WIDTH = 10

    def __init__(self, receiver, delta=True):
        if receiver:
            cname = self.__class__.__name__
            raise ValueError("{0} don't allows receiving".format(cname))

        self.headers = None
        self.line_format = ""
        self.prev = {}
        self.delta = delta
        self.fd = sys.stdout

    def send(self, data):
        if self.headers is None:
            self.headers = sorted(data)

            for pos, header in enumerate(self.headers):
                self.line_format += "{%s:>%s}" % (pos,
                                                  max(len(header) + 1,
                                                      self.MIN_COL_WIDTH))

            print self.line_format.format(*self.headers)

        if self.delta:
            vals = [data[header].value - self.prev.get(header, 0)
                    for header in self.headers]

            self.prev.update(dict((header, data[header].value)
                             for header in self.headers))
        else:
            vals = [data[header].value for header in self.headers]

        self.fd.write(self.line_format.format(*vals) + "\n")

    def recv(self, timeout=None):
        cname = self.__class__.__name__
        raise ValueError("{0} don't allows receiving".format(cname))


class FileTransport(StdoutTransport):
    def __init__(self, receiver, fname, delta=True):
        StdoutTransport.__init__(self, receiver, delta)
        self.fd = open(fname, "w")


class UDPTransport(ITransport):
    def __init__(self, receiver, ip, port, packer_cls):
        self.port = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        if receiver:
            self.port.bind((ip, port))
            self.packer_cls = packer_cls
            self.packers = {}
        else:
            self.packer = packer_cls()
            self.dst = (ip, port)

    def send(self, data):
        raw_data = self.packer.pack(data)
        self.port.sendto(raw_data, self.dst)

    def recv(self, timeout=None):
        r, _, _ = select.select([self.port], [], [], timeout)
        if len(r) != 0:
            raw_data, addr = self.port.recvfrom(10000)
            packer = self.packers.setdefault(addr, self.packer_cls())
            return addr, packer.unpack(raw_data)
        else:
            raise Timeout()


# -------------------------- Factory function --------------------------------


def create_protocol(uri, receiver=False):
    parsed_uri = urlparse(uri)
    if parsed_uri.scheme == 'stdout':
        return StdoutTransport(receiver)
    elif parsed_uri.scheme == 'udp':
        ip, port = parsed_uri.netloc.split(":")

        if receiver:
            packer_cls = StructSerializerRecv
        else:
            packer_cls = StructSerializerSend

        return UDPTransport(receiver, ip=ip, port=int(port),
                            packer_cls=packer_cls)
    elif parsed_uri.scheme == 'file':
        return FileTransport(receiver, parsed_uri.path)
    else:
        templ = "Can't instantiate transport from {0!r}"
        raise ValueError(templ.format(uri))
