# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

import logging
import os
import sys

from cherrypy import wsgiserver

from xivo import http_helpers
from xivo.auth_helpers import TokenRenewer

from xivo_webi import plugin_manager
from xivo_webi.flask_controller import FlaskController

from xivo_webi.auth import new_auth_client

logger = logging.getLogger(__name__)


class Controller(object):

    def __init__(self, config):
        self._config = config
        try:
            self._listen_addr = config['https']['listen']
            self._listen_port = config['https']['port']
            self._ssl_cert_file = config['https']['certificate']
            self._ssl_key_file = config['https']['private_key']
            self._ssl_ciphers = config['https']['ciphers']
            self._foreground = config['foreground']
            self._log_level = config['log_level']
            self._debug = config['debug']
            self._bind_addr = (self._listen_addr, self._listen_port)
            logger.debug('private key: %s', self._ssl_key_file)
        except KeyError as e:
            logger.error('Missing configuration to start the application: %s', e)
            sys.exit(1)

        flask_controller = FlaskController(self._config)

        self._flask_app = flask_controller.get_app()
        plugin_manager.load_plugins(self._flask_app)

    def run(self):
        self._check_file_readable(self._ssl_key_file)
        self._check_file_readable(self._ssl_cert_file)

        token_renewer = self._token_renewer(self._flask_app)

        wsgi_app = wsgiserver.WSGIPathInfoDispatcher({'/': self._flask_app})
        server = wsgiserver.CherryPyWSGIServer(bind_addr=self._bind_addr, wsgi_app=wsgi_app)
        server.ssl_adapter = http_helpers.ssl_adapter(self._ssl_cert_file,
                                                      self._ssl_key_file,
                                                      self._ssl_ciphers)

        logger.debug('WSGIServer starting... uid: %s, listen: %s:%s', os.getuid(), self._bind_addr[0], self._bind_addr[1])
        for route in http_helpers.list_routes(self._flask_app):
            logger.debug(route)

        try:
            with token_renewer:
                server.start()
        except KeyboardInterrupt:
            server.stop()

    def _check_file_readable(self, file_path):
        with open(file_path, 'r'):
            pass

    def _token_renewer(self, app):
        token_renewer = TokenRenewer(new_auth_client(app.config['auth']))
        def on_token_change(token_id):
            app.config['service_token'] = token_id
        token_renewer.subscribe_to_token_change(on_token_change)

        return token_renewer
