#!/usr/bin/env python

# std
import os
import pwd
import grp
import functools
import socket
import random
import re
import logging
import sys
import socket

# ssl check
try:
    import ssl
except ImportError:
    ssl = None

# install checks
try:
    import tornado
except ImportError:
    print "Tornado is not installed but is required. Please run 'pip install tornado==2.2.1'"
    sys.exit(1)
    
try:
    import setproctitle
except ImportError:
    print "setproctitle is not installed but is required. Please run 'pip install setproctitle'"
    sys.exit(1)

# Just in case some tit tries to run the file in /bin
try:
    from blackhole import __pname__
except ImportError:
    print "blackhole is not installed, please install it using the instructions in the README file"
    sys.exit(1)

# pip stuff
import setproctitle
import tornado
from tornado import ioloop
from tornado.options import options
from deiman.deiman import Deiman

# blackhole
from blackhole import __pname__, __desc__
from blackhole.opts import *
from blackhole.connection import connection_ready, sockets
from blackhole.ssl_utils import verify_ssl_opts, BlackholeSSLException, sslkwargs


setproctitle.setproctitle(__pname__)
tornado.options.parse_command_line()
if options.conf and os.path.exists(options.conf):
    tornado.options.parse_config_file(options.conf)
if options.ssl and not ssl:
    msg = "Unable to use SSL as ssl library is not compiled in"
    log.error(msg)
    print msg
    sys.exit(1)

logging.basicConfig(format="%(message)s")
log = logging.getLogger(__name__)
file_handler = logging.FileHandler(options.log)
file_handler.setLevel(logging.INFO)
file_formatter = logging.Formatter("%(asctime)s - %(message)s")
file_handler.setFormatter(file_formatter)
log.addHandler(file_handler)


if __name__ == "__main__":
    action = None
    for arg in sys.argv[1:]:
        if not arg.startswith("--"):
            action = arg
    if action not in ('start', 'stop', 'status') or action is None:
        print_help()
        sys.exit(2)
    
    if len(sys.argv) == 1:
        print_help()
        sys.exit(2)

    if options.ssl:
        try:
            verify_ssl_opts()
        except BlackholeSSLException, e:
            log.error(e)
            sys.exit(1)
        sslkwargs['keyfile'] = options.ssl_key
        sslkwargs['certfile'] = options.ssl_cert
    
    io_loop = ioloop.IOLoop.instance()
    d = Deiman(options.pid)
    
    if action == "start":
        socks = sockets()
        d.start()
    elif action == "stop":
        d.stop()
        sys.exit(0)
    elif action == "status":
        d.status()
        sys.exit(0)

    for _, sock in socks.iteritems():
        callback = functools.partial(connection_ready, sock)
        io_loop.add_handler(sock.fileno(), callback, io_loop.READ)
    
    try:
        # Attempt to switch group we run as
        try:
            os.setgid(grp.getgrnam(options.group).gr_gid)
        except KeyError:
            log.error("Group '%s' does not exist" % options.group)
            sys.exit(1)
        except OSError:
            log.error("You do not have permission to switch to group '%s'" % options.group)
            sys.exit(1)

        # Attempt to switch user we run as
        try:
            os.setuid(pwd.getpwnam(options.user).pw_uid)
        except KeyError:
            log.error("User '%s' does not exist" % options.user)
            sys.exit(1)
        except OSError:
            log.error("You do not have permission to switch to user '%s'" % options.user)
            sys.exit(1)

        io_loop.start()
    except KeyboardInterrupt, SystemExit:
        io_loop.stop()
        d.stop()
        sys.exit(0)
