import signal
import sys
import time

from thumbor.utils import logger
import tornado.ioloop


def signal_handler(server, config, sig, frame):
    io_loop = tornado.ioloop.IOLoop.instance()

    def stop_loop(now, deadline):
        if now < deadline and (io_loop._callbacks or io_loop._timeouts):
            logger.debug('Waiting for next tick')
            now += 1
            io_loop.add_timeout(now, stop_loop, now, deadline)
        else:
            io_loop.stop()
            logger.debug('Shutdown finally')

    def stop_server(now, deadline):
        if now < deadline:
            logger.debug('Waiting for next tick')
            now += 1
            io_loop.add_timeout(now, stop_server, now, deadline)
        else:
            server.stop()
            logger.debug('Stopped http server.')
            logger.debug('Will shutdown io in maximum %d seconds ...',
                         config.MAX_WAIT_SECONDS_BEFORE_IO_SHUTDOWN)
            now = time.time()
            stop_loop(now, now + config.MAX_WAIT_SECONDS_BEFORE_IO_SHUTDOWN)

    def shutdown():
        logger.debug('Stopping http server (i.e. stopping accepting new requests) in %d seconds ...',
                     config.MAX_WAIT_SECONDS_BEFORE_SERVER_SHUTDOWN)
        now = time.time()
        stop_server(now, now + config.MAX_WAIT_SECONDS_BEFORE_SERVER_SHUTDOWN)

    logger.warning('Caught signal: %d. Shutting down server.', sig)
    io_loop.add_callback_from_signal(shutdown)


def setup_signal_handler(server, config):

    def server_sig_handler(sig, frame):
        signal_handler(server, config, sig, frame)
        if sig == signal.SIGINT:
            sys.stdout.write('\n')
            sys.stdout.write("-- thumbor closed by user interruption --\n")

    signal.signal(signal.SIGTERM, server_sig_handler)
    signal.signal(signal.SIGINT, server_sig_handler)
