#!/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(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()
