# -*- coding: utf-8 -*-
import os
import uuid
import logging
import tornado.httpclient
import tornado.escape
import tornado.ioloop
import tornado.web
import tornado.auth
import tornado.httpserver
import tornado.websocket
import tornado.template
from sayuri.module import model as mdl
from sayuri.module import recognizers
from sayuri.module import actions


class Application(tornado.web.Application):
    observers = {}

    def __init__(self):
        from sayuri.env import Environment
        secret_key = Environment().secret_key()

        handlers = [
            (r"/", IndexHandler),
            (r"/home", HomeHandler),
            (r"/auth/login", LoginHandler),
            (r"/auth/logout", LogoutHandler),
            (r"/conference", ConferenceHandler),
            (r"/conference/image", ImageHandler),
            (r"/sayurisocket", ClientSocketHandler),
        ]
        settings = dict(
            login_url="/auth/login",
            template_path=os.path.join(os.path.dirname(__file__), "templates"),
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            xsrf_cookies=True,
            cookie_secret=secret_key,
            debug=True,
        )

        # load and store prediction model
        actions.FaceAction.store_machine()
        tornado.web.Application.__init__(self, handlers, **settings)

    @classmethod
    def add_conference(cls, user, conference_key):
        if conference_key not in cls.observers:
            key = MessageManager.make_client_key(user, conference_key)
            instance = tornado.ioloop.IOLoop.instance()
            messenger = MessageManager(user, conference_key)
            cls.observers[key] = recognizers.SayuriRecognitionObserver(
                instance.add_timeout, messenger.send, user, conference_key)
            cls.observers[key].set_recognizer(recognizers.TimeRecognizer(),
                                              recognizers.FaceDetectIntervalRecognizer(),
                                              recognizers.FaceRecognizer())
            cls.observers[key].set_action(actions.TimeManagementAction(),
                                          actions.FaceDetectAction(),
                                          actions.FaceAction())
            cls.observers[key].run()
            return True
        else:
            return False

    @classmethod
    def get_conference_observer(cls, key):
        if key in cls.observers:
            return cls.observers[key]
        else:
            return None

    @classmethod
    def remove_conference(cls, key):
        if key in cls.observers:
            cls.observers[key].stop()
            del cls.observers[key]
            return True
        else:
            return False


class MessageManager(object):

    def __init__(self, user, conference_key):
        self.client = self.make_client_key(user, conference_key)

    @classmethod
    def make_client_key(cls, user, conference_key):
        if user and conference_key:
            return user + ":" + conference_key
        else:
            return ""

    def send(self, message):
        if not message:
            return False
        else:
            ClientSocketHandler.broadcast(self.client, message)
            return True


class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        return self.get_secure_cookie("user")

    def get_current_user_str(self):
        return tornado.escape.to_unicode(self.get_current_user())

    def get_current_conference_key(self):
        return tornado.escape.to_unicode(self.get_secure_cookie(mdl.Conference.KEY))

    def get_current_key(self):
        return MessageManager.make_client_key(self.get_current_user_str(), self.get_current_conference_key())


class HomeHandler(BaseHandler):
    def get(self):
        self.render("home.html")


class LoginHandler(BaseHandler):
    def get(self):
        self.redirect("/home")

    def post(self):
        #todo implements authorization
        self.set_secure_cookie("user", "Guest")
        self.redirect("/")


class LogoutHandler(BaseHandler):
    def get(self):
        Application.remove_conference(self.get_current_key())
        self.clear_cookie("user")
        self.clear_cookie(mdl.Conference.KEY)
        self.redirect("/home")


class IndexHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        self.render("index.html")


class ConferenceHandler(BaseHandler):

    @tornado.web.authenticated
    def get(self):
        # return conference list of current use.
        user = self.get_current_user_str()
        conference_key = self.get_current_conference_key()
        key = self.get_current_key()
        cs = []
        conference = ""
        if user:
            # show only conference of now
            # cs = Conference.get_users_conference(user, 0)
            pass

        if conference_key:
            conference = mdl.Conference.get(conference_key)
            cs.append(conference)