#!/usr/bin/env python
# encoding: utf-8
#
#    Copyright (c) 2013-2014+ Anton Tyurin <noxiouz@yandex.ru>
#    Copyright (c) 2013-2014 Other contributors as noted in the AUTHORS file.
#
#    This file is part of Cocaine.
#
#    Cocaine is free software; you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as published by
#    the Free Software Foundation; either version 3 of the License, or
#    (at your option) any later version.
#
#    Cocaine is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#    GNU Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public License
#    along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import print_function

import logging
import socket
import sys

import tornado.httpserver
from tornado.ioloop import IOLoop
from tornado.options import define, options
from tornado.options import parse_config_file, parse_command_line

from cocaine.flow.app import FlowRestServer
from cocaine.flow.app import FlowInitializationError

log = logging.getLogger()

RESTGroup = 'RestServer'
ServerGroup = 'HTTPServer'

# Webserver options
define('port', default=8888, group=ServerGroup,
       help='run on the given port', type=int)

define('host', default="", group=ServerGroup,
       help='run on the given host', type=str)

define('procs', default=-1, group=ServerGroup,
       help='Procs number', type=int)

# REST server options
define('registry', group=RESTGroup,
       help='Docker-registry host:port', type=str)

define('cocaine_host', group=RESTGroup,
       help='Cocaine-runtime',
       type=str, default="localhost"),

define('cocaine_port', group=RESTGroup,
       help='Cocaine-runtime',
       type=int, default=10053),

define('docker', group=RESTGroup,
       help='Docker daemon endpoint', type=str)

define('cookie_secret', group=RESTGroup,
       help='cookie secret key', type=str)

define('debug', group=RESTGroup,
       help='enable debug mode', type=bool, default=False)

# configuration file
define('config', group=ServerGroup,
       type=str, help='path to config file',
       callback=lambda path: parse_config_file(path, final=False))


def check_options():
    for opt, value in options.group_dict(RESTGroup).iteritems():
        if value is None:
            log.error("Option '%s' should have a value", opt)
            # Print to stderr as fallback
            print("Option '%s' should have a value" % opt, file=sys.stderr)
            options.print_help()
            exit(1)


def main():
    options.add_parse_callback(check_options)
    parse_command_line()

    # bind sockets
    try:
        sockets = tornado.netutil.bind_sockets(options.port,
                                               options.host)
    except socket.error as err:
        log.error("Unable to use endpoint %s:%d %s",
                  options.host,
                  options.port, err)
        exit(1)

    # Should I fork?
    if options.procs > -1:
        # 0 value means: "create as many procs as CPUs"
        tornado.process.fork_processes(options.procs)

    # initialize RestServer web app
    rest_server_settings = options.group_dict(RESTGroup)
    try:
        app = FlowRestServer(**rest_server_settings)
    except FlowInitializationError as err:
        log.error(err)
        exit(1)
    except Exception as err:
        log.error("Unknown error %s", err)
        exit(1)
    # create server
    server = tornado.httpserver.HTTPServer(app)
    # attach handlers
    server.add_sockets(sockets)
    log.info("Listening to %s",
             ' '.join(('%s:%d' % s.getsockname()[:2] for s in sockets)))
    IOLoop.instance().start()

if __name__ == "__main__":
    main()
