# ~*~ coding: utf-8 ~*~

import logging
import time
import threading
from gevent import monkey

from flask import Flask
from flask_socketio import SocketIO
from .conf import config
from .service import service

monkey.patch_all()

logger = logging.getLogger(__file__)


__version__ = '0.4.0'


class Luna(Flask):
    service = service
    proxy_list = {}
    clients = {}
    active = True

    def bootstrap(self):
        print(time.ctime())
        print(
            'Luna version %s, more see https://www.jumpserver.org' % __version__)
        print('Starting web server at %(host)s:%(port)s' %
              {'host': self.config['BIND_HOST'],
               'port': self.config['LISTEN_PORT']})
        print('Quit the server with CONTROL-C.')
        self.heatbeat()

    def handle_task(self, tasks):
        for task in tasks:
            if task['name'] == 'kill_proxy':
                try:
                    proxy_log_id = int(task['proxy_log_id'])
                except ValueError:
                    pass
                if proxy_log_id in self.proxy_list:
                    client_channel, backend_channel = self.proxy_list.get(
                        proxy_log_id)
                    client_channel.send('Terminated by admin  ')
                    backend_channel.close()
                    client_channel.close()

            data = {
                "proxy_log_id": proxy_log_id,
                "date_finished": time.time(),
            }
            self.service.finish_proxy_log(data)

    def heatbeat(self):
        def _keep():
            while True:
                result = service.terminal_heatbeat()
                if result is None:
                    logger.warning('Terminal heatbeat failed or '
                                   'Terminal need accepted by administrator')
                else:
                    tasks = result.get('tasks')
                    if tasks:
                        logger.info('Receive task: %s' % tasks)
                        self.handle_task(tasks)
                time.sleep(config.HEATBEAT_INTERVAL)

        thread = threading.Thread(target=_keep)
        thread.daemon = True
        thread.start()

    def stop(self):
        self.active = False
        for i in Luna.clients:
            i.disconnect()
        socket_io.stop()

async_mode = 'gevent'
app = Luna(__name__, template_folder='dist')
socket_io = SocketIO(app, async_mode=async_mode)
app.config.update(**config)
