import logging
logger = logging.getLogger(__file__)

from os import path as p

from autobahn.websocket import listenWS

from webob import Response

from west.base import BaseApp
from west.config import Config
from west.utils import load_callback


CONFIG_KEY = "west.socket"
CONFIG_SEP = "."


class SocketApp(BaseApp):
    
    def __init__(self, environ, **config):
        BaseApp.__init__(self, environ, **config)
        # url mapping
        self.connect("/socket", action="call")
        # open sockets
        self.urls = dict()
        self.__open_sockets()

    def __c(self, option, default=None, _type=str):
        option = CONFIG_KEY + "." + option
        return _type(self.config.get(option, default))

    def __add_socket(self, config_func):
        # read config
        host = config_func("host")
        port = config_func("port", _type=int)
        debug = config_func("debug", default=True, _type=bool)
        # module loading
        factory_m = load_callback(config_func("factory"))
        protocol_m = load_callback(config_func("protocol"))
        # socket url
        url = "ws://%s:%s" % (host, port)
        # debug
        logger.debug(url)
        #  init factory
        factory = factory_m(url, debug=debug)
        factory.app = self
        factory.get_config = config_func
        factory.protocol = protocol_m
        # listen
        listenWS(factory)
        # call start after init method
        factory.start()
        # for next use
        return url

    def __open_sockets(self):
        for section in self.__c("sockets").split():
            # prepare conf cb
            section = "socket:" + section
            config_func = Config().get_func(section, CONFIG_KEY, CONFIG_SEP)
            # attach socket
            self.urls[config_func("name")] = self.__add_socket(config_func)

    def call(self, environ, req, **kw):
        self.register(environ, CONFIG_KEY+":"+"url",
                      self.urls[kw.get("factory", "default")])


def socket_app_factory(environ, **config):
    return SocketApp(environ, **config)


K = "sample.app"

class DemoApp(SocketApp):
    
    def __init__(self, environ, **config):
        SocketApp.__init__(self, environ, **config)
        # url mapping
        self.connect("/index", action="index")

    def respond(self, environ, start_response):
        path = self.registry(environ, key=K)
        if path and p.exists(path):
            with open(path) as f:
                res = Response(body=f.read())
                return res(environ, start_response)
        return SocketApp.respond(self, environ, start_response)

    def index(self, environ, req, **kw):
        self.register(environ, K, p.join("static", "index.html"))


def demo_app_factory(environ, **config):
    return DemoApp(environ, **config)
