#!/usr/bin/env python
#
# Copyright 2016 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.
#

"""
PON Simulator process, able to move packets across NNI and UNIs, as well
as take MGMT calls via gRPC.
It can only work on Linux.
"""
import argparse
import os

import yaml
from twisted.internet.defer import inlineCallbacks

from common.structlog_setup import setup_logging
from grpc_server import GrpcServer
from ponsim import PonSim
from realio import RealIo

defs = dict(
    config=os.environ.get('CONFIG', './ponsim.yml'),
    grpc_port=int(os.environ.get('GRPC_PORT', 50060)),
    name=os.environ.get('NAME', 'pon1'),
    onus=int(os.environ.get("ONUS", 1))
)


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'''
 ____   __   __ _  ____  __  _  _
(  _ \ /  \ (  ( \/ ___)(  )( \/ )
 ) __/(  O )/    /\___ \ )( / \/ \
(__)   \__/ \_)__)(____/(__)\_)(_/
'''

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


def parse_args():

    parser = argparse.ArgumentParser()

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

    _help = ('port number of the GRPC service exposed by voltha (default: %s)'
             % defs['grpc_port'])
    parser.add_argument('-g', '--grpc-port',
                        dest='grpc_port',
                        action='store',
                        default=defs['grpc_port'],
                        help=_help)

    _help = ('number of ONUs to simulate (default: %d)' % defs['onus'])
    parser.add_argument('-o', '--onus',
                        dest='onus',
                        action='store',
                        type=int,
                        default=defs['onus'],
                        help=_help)

    _help = ('name of the PON natework used as a prefix for all network'
             ' resource created on behalf of the PON (default: %s)' %
             defs['name'])
    parser.add_argument('-N', '--name',
                        dest='name',
                        action='store',
                        default=defs['name'],
                        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 = 'enable generation of simulated alarms'
    parser.add_argument('-a', '--alarm-simulation',
                        dest='alarm_simulation',
                        action='store_true',
                        default=False,
                        help=_help)

    _help = 'frequency of simulated alarms (in seconds)'
    parser.add_argument('-f', '--alarm-frequency',
                        dest='alarm_frequency',
                        action='store',
                        type=int,
                        metavar="[5-300]",
                        choices=range(5,301),
                        default=60,
                        help=_help)

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

    args = parser.parse_args()

    return args


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.name,
                                 verbosity_adjust=verbosity_adjust)

        # components
        self.io = None
        self.ponsim = None
        self.grpc_server = None

        self.alarm_config = dict()
        self.alarm_config['simulation'] = self.args.alarm_simulation
        self.alarm_config['frequency'] = self.args.alarm_frequency

        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):
        try:
            self.log.info('starting-internal-components')

            iface_map = self.setup_networking_assets(self.args.name,
                                                     self.args.onus)
            self.io = yield RealIo(iface_map).start()
            self.ponsim = PonSim(self.args.onus, self.io.egress, self.alarm_config)
            self.io.register_ponsim(self.ponsim)

            self.grpc_server = GrpcServer(self.args.grpc_port, self.ponsim)
            yield self.grpc_server.start()

            self.log.info('started-internal-services')

        except Exception, e:
            self.log.exception('startup-failed', e=e)

    @inlineCallbacks
    def shutdown_components(self):
        """Execute before the reactor is shut down"""
        self.log.info('exiting-on-keyboard-interrupt')
        try:
            if self.io is not None:
                yield self.io.stop()
            self.teardown_networking_assets(self.args.name, self.args.onus)
            if self.grpc_server is not None:
                yield self.grpc_server.stop()
        except Exception, e:
            self.log.exception('shutdown-failed', e=e)

    def start_reactor(self):
        from twisted.internet import reactor
        reactor.callWhenRunning(
            lambda: self.log.info('twisted-reactor-started'))
        reactor.addSystemEventTrigger('before', 'shutdown',
                                      self.shutdown_components)
        reactor.run()

    def setup_networking_assets(self, prefix, n_unis):
        # setup veth pairs for NNI and each UNI, using prefix and port numbers
        port_map = dict()
        for portnum in [0] + range(128, 128 + n_unis):
            external_name = '%s_%d' % (prefix, portnum)
            internal_name = external_name + 'sim'
            os.system('sudo ip link add dev {} type veth peer name {}'.format(
                external_name, internal_name
            ))
            os.system('sudo ip link set {} up'.format(external_name))
            os.system('sudo ip link set {} up'.format(internal_name))
            if portnum == 0:
                os.system('sudo brctl addif ponmgmt {}'.format(external_name))
            port_map[portnum] = internal_name
        return port_map

    def teardown_networking_assets(self, prefix, n_unis):
        # undo all the networking stuff
        for portnum in [0] + range(128, 128 + n_unis):
            external_name = '%s_%d' % (prefix, portnum)
            os.system('sudo ip link del {}'.format(external_name))


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