#!/usr/bin/env python
#
# Copyright 2017 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import argparse
import os
import sys
import yaml
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks

base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_dir)
sys.path.append(os.path.join(base_dir, '/netconf/protos/third_party'))

from common.structlog_setup import setup_logging
from common.utils.dockerhelpers import get_my_containers_name
from common.utils.nethelpers import get_my_primary_local_ipv4
from netconf.grpc_client.grpc_client import GrpcClient
from netconf.nc_server import NCServer

defs = dict(
    config=os.environ.get('CONFIG', './netconf.yml'),
    consul=os.environ.get('CONSUL', 'localhost:8500'),
    external_host_address=os.environ.get('EXTERNAL_HOST_ADDRESS',
                                         get_my_primary_local_ipv4()),
    netconf_port=os.environ.get('NETCONF_PORT', '1830'),
    server_private_key_file=os.environ.get('SERVER_PRIVATE_KEY_FILE',
                                           'server.key'),
    server_public_key_file=os.environ.get('SERVER_PRIVATE_KEY_FILE',
                                          'server.key.pub'),
    client_public_keys_file=os.environ.get('CLIENT_PUBLIC_KEYS_FILE',
                                           'client_keys'),
    client_passwords_file=os.environ.get('CLIENT_PASSWORD_FILE',
                                         'client_passwords'),
    grpc_endpoint=os.environ.get('GRPC_ENDPOINT', 'localhost:50055'),
    fluentd=os.environ.get('FLUENTD', None),
    instance_id=os.environ.get('INSTANCE_ID', os.environ.get('HOSTNAME', '1')),
    internal_host_address=os.environ.get('INTERNAL_HOST_ADDRESS',
                                         get_my_primary_local_ipv4()),
    work_dir=os.environ.get('WORK_DIR', '/tmp/netconf')
)


def parse_args():
    parser = argparse.ArgumentParser()

    _help = ('Path to netconf.yml config file (default: %s). '
             'If relative, it is relative to main.py of ofagent.'
             % defs['config'])
    parser.add_argument('-c', '--config',
                        dest='config',
                        action='store',
                        default=defs['config'],
                        help=_help)

    _help = '<hostname>:<port> to consul agent (default: %s)' % defs['consul']
    parser.add_argument(
        '-C', '--consul', dest='consul', action='store',
        default=defs['consul'],
        help=_help)

    _help = ('<hostname> or <ip> at which netconf is reachable from '
             'outside the cluster (default: %s)' % defs[
                 'external_host_address'])
    parser.add_argument('-E', '--external-host-address',
                        dest='external_host_address',
                        action='store',
                        default=defs['external_host_address'],
                        help=_help)

    _help = ('<port> of netconf server (default: %s). (If not '
             'specified (None), the port from the config file is used'
             % defs['netconf_port'])
    parser.add_argument('-N', '--netconf_port',
                        dest='netconf_port',
                        action='store',
                        default=defs['netconf_port'],
                        help=_help)

    _help = (
    '<server private key file name> used by the netconf server. (If not '
    'specified (None), the file name from the config file is used (default: %s)'
    % defs['server_private_key_file'])
    parser.add_argument('-S', '--server_private_key_file',
                        dest='server_private_key_file',
                        action='store',
                        default=defs['server_private_key_file'],
                        help=_help)

    _help = ('<server public key file name> used by the netconf server. (If '
             'not specified (None), the file name from the config file is '
             'used (default: %s) '
             % defs['server_public_key_file'])
    parser.add_argument('-P', '--server_public_key_file',
                        dest='server_public_key_file',
                        action='store',
                        default=defs['server_public_key_file'],
                        help=_help)

    _help = ('<client public key file name> used by the netconf server. (If '
             'not specified (None), the file name from the config file is '
             'used(default: %s) '
             % defs['client_public_keys_file'])
    parser.add_argument('-X', '--client_public_keys_file',
                        dest='client_public_keys_file',
                        action='store',
                        default=defs['client_public_keys_file'],
                        help=_help)

    _help = ('<client password file name> used by the netconf server. (If '
             'not specified (None), the file name from the config file is '
             'used (default: %s) '
             % defs['client_passwords_file'])
    parser.add_argument('-U', '--client_passwords_file',
                        dest='client_passwords_file',
                        action='store',
                        default=defs['client_passwords_file'],
                        help=_help)

    _help = ('<hostname>:<port> to fluentd server (default: %s). (If not '
             'specified (None), the address from the config file is used'
             % defs['fluentd'])
    parser.add_argument('-F', '--fluentd',
                        dest='fluentd',
                        action='store',
                        default=defs['fluentd'],
                        help=_help)

    _help = ('gRPC end-point to connect to. It can either be a direct'
             'definition in the form of <hostname>:<port>, or it can be an'
             'indirect definition in the form of @<service-name> where'
             '<service-name> is the name of the grpc service as registered'
             'in consul (example: @voltha-grpc). (default: %s'
             % defs['grpc_endpoint'])
    parser.add_argument('-G', '--grpc-endpoint',
                        dest='grpc_endpoint',
                        action='store',
                        default=defs['grpc_endpoint'],
                        help=_help)

    _help = ('<hostname> or <ip> at which netconf server is reachable from '
             'inside the cluster (default: %s)' % defs[
                 'internal_host_address'])
    parser.add_argument('-H', '--internal-host-address',
                        dest='internal_host_address',
                        action='store',
                        default=defs['internal_host_address'],
                        help=_help)

    _help = ('unique string id of this netconf server instance (default: %s)'
             % defs['instance_id'])
    parser.add_argument('-i', '--instance-id',
                        dest='instance_id',
                        action='store',
                        default=defs['instance_id'],
                        help=_help)

    _help = 'omit startup banner log lines'
    parser.add_argument('-n', '--no-banner',
                        dest='no_banner',
                        action='store_true',
                        default=False,
                        help=_help)

    _help = "suppress debug and info logs"
    parser.add_argument('-q', '--quiet',
                        dest='quiet',
                        action='count',
                        help=_help)

    _help = 'enable verbose logging'
    parser.add_argument('-v', '--verbose',
                        dest='verbose',
                        action='count',
                        help=_help)

    _help = ('work dir to compile and assemble generated files (default=%s)'
             % defs['work_dir'])
    parser.add_argument('-w', '--work-dir',
                        dest='work_dir',
                        action='store',
                        default=defs['work_dir'],
                        help=_help)

    _help = ('use docker container name as netconf server instance id'
             ' (overrides -i/--instance-id option)')
    parser.add_argument('--instance-id-is-container-name',
                        dest='instance_id_is_container_name',
                        action='store_true',
                        default=False,
                        help=_help)

    args = parser.parse_args()

    # post-processing

    if args.instance_id_is_container_name:
        args.instance_id = get_my_containers_name()

    return args


def load_config(args):
    path = args.config
    if path.startswith('.'):
        dir = os.path.dirname(os.path.abspath(__file__))
        path = os.path.join(dir, path)
    path = os.path.abspath(path)
    with open(path) as fd:
        config = yaml.load(fd)
    return config


banner = r'''
 _   _      _                   __   ____
| \ | | ___| |_ ___ ___  _ __  / _| / ___|  ___ _ ____   _____ _ __
|  \| |/ _ \ __/ __/ _ \| '_ \| |_  \___ \ / _ \ '__\ \ / / _ \ '__|
| |\  |  __/ || (_| (_) | | | |  _|  ___) |  __/ |   \ V /  __/ |
|_| \_|\___|\__\___\___/|_| |_|_|   |____/ \___|_|    \_/ \___|_|
'''


def print_banner(log):
    for line in banner.strip('\n').splitlines():
        log.info(line)
    log.info('(to stop: press Ctrl-C)')


class Main(object):
    def __init__(self):

        self.args = args = parse_args()
        self.config = load_config(args)

        verbosity_adjust = (args.verbose or 0) - (args.quiet or 0)
        self.log = setup_logging(self.config.get('logging', {}),
                                 args.instance_id,
                                 verbosity_adjust=verbosity_adjust,
                                 fluentd=args.fluentd)

        # components
        self.nc_server = None
        self.grpc_client = None  # single, shared gRPC client to Voltha

        self.netconf_server_started = False

        self.exiting = False

        if not args.no_banner:
            print_banner(self.log)

        self.startup_components()

    def start(self):
        self.start_reactor()  # will not return except Keyboard interrupt

    @inlineCallbacks
    def startup_components(self):
        self.log.info('starting')
        args = self.args

        self.grpc_client = yield \
            GrpcClient(args.consul, args.work_dir, args.grpc_endpoint)

        self.nc_server =  yield \
                NCServer(int(args.netconf_port),
                         args.server_private_key_file,
                         args.server_public_key_file,
                         args.client_public_keys_file,
                         args.client_passwords_file,
                         self.grpc_client)

        # set on start callback
        self.grpc_client.set_on_start_callback(self._start_netconf_server)

        # set the callback if there is a reconnect with voltha.
        self.grpc_client.set_reconnect_callback(self.nc_server.reload_capabilities)

        # start grpc client
        self.grpc_client.start()

        self.log.info('started')

    @inlineCallbacks
    def _start_netconf_server(self):
        if not self.netconf_server_started:
            self.log.info('starting')
            yield self.nc_server.start()
            self.netconf_server_started = True
            self.log.info('started')
        else:
            self.log.info('server-already-started')

    @inlineCallbacks
    def shutdown_components(self):
        """Execute before the reactor is shut down"""
        self.log.info('exiting-on-keyboard-interrupt')
        self.exiting = True

        if self.grpc_client is not None:
            yield self.grpc_client.stop()

        if self.nc_server is not None:
            yield self.nc_server.stop()


    def start_reactor(self):
        reactor.callWhenRunning(
            lambda: self.log.info('twisted-reactor-started'))

        reactor.addSystemEventTrigger('before', 'shutdown',
                                      self.shutdown_components)
        reactor.run()


if __name__ == '__main__':
    Main().start()
