#!/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="[30-300]",
                        choices=range(30,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()
