"""
Encapsulate the different transports available to Salt.

This includes server side transport, for the ReqServer and the Publisher
"""


class ReqServerChannel:
    """
    Factory class to create a communication channels to the ReqServer
    """

    def __init__(self, opts):
        self.opts = opts

    @staticmethod
    def factory(opts, **kwargs):
        # Default to ZeroMQ for now
        ttype = "zeromq"

        # determine the ttype
        if "transport" in opts:
            ttype = opts["transport"]
        elif "transport" in opts.get("pillar", {}).get("master", {}):
            ttype = opts["pillar"]["master"]["transport"]

        # switch on available ttypes
        if ttype == "zeromq":
            import salt.transport.zeromq

            return salt.transport.zeromq.ZeroMQReqServerChannel(opts)
        elif ttype == "tcp":
            import salt.transport.tcp

            return salt.transport.tcp.TCPReqServerChannel(opts)
        elif ttype == "local":
            import salt.transport.local

            return salt.transport.local.LocalServerChannel(opts)
        else:
            raise Exception("Channels are only defined for ZeroMQ and TCP")
            # return NewKindOfChannel(opts, **kwargs)

    def pre_fork(self, process_manager):
        """
        Do anything necessary pre-fork. Since this is on the master side this will
        primarily be bind and listen (or the equivalent for your network library)
        """

    def post_fork(self, payload_handler, io_loop):
        """
        Do anything you need post-fork. This should handle all incoming payloads
        and call payload_handler. You will also be passed io_loop, for all of your
        asynchronous needs
        """


class PubServerChannel:
    """
    Factory class to create subscription channels to the master's Publisher
    """

    @staticmethod
    def factory(opts, **kwargs):
        # Default to ZeroMQ for now
        ttype = "zeromq"

        # determine the ttype
        if "transport" in opts:
            ttype = opts["transport"]
        elif "transport" in opts.get("pillar", {}).get("master", {}):
            ttype = opts["pillar"]["master"]["transport"]

        # switch on available ttypes
        if ttype == "zeromq":
            import salt.transport.zeromq

            return salt.transport.zeromq.ZeroMQPubServerChannel(opts, **kwargs)
        elif ttype == "tcp":
            import salt.transport.tcp

            return salt.transport.tcp.TCPPubServerChannel(opts)
        elif ttype == "local":  # TODO:
            import salt.transport.local

            return salt.transport.local.LocalPubServerChannel(opts, **kwargs)
        else:
            raise Exception("Channels are only defined for ZeroMQ and TCP")
            # return NewKindOfChannel(opts, **kwargs)

    def pre_fork(self, process_manager, kwargs=None):
        """
        Do anything necessary pre-fork. Since this is on the master side this will
        primarily be used to create IPC channels and create our daemon process to
        do the actual publishing
        """

    def publish(self, load):
        """
        Publish "load" to minions
        """
        raise NotImplementedError()
