# osmo_gsm_tester: specifics for running an SRS eNodeB process
#
# Copyright (C) 2020 by sysmocom - s.f.m.c. GmbH
#
# Author: Pau Espin Pedrol <pespin@sysmocom.de>
#
# 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 os
import pprint

from ..core import log, util, config, template, process, remote
from ..core import schema
from . import enb
from . import rfemu

def on_register_schemas():
    config_schema = {
        'license_server_addr': schema.IPV4,
        }
    schema.register_config_schema('amarisoft', config_schema)

def rf_type_valid(rf_type_str):
    return rf_type_str in ('uhd', 'zmq')

class AmarisoftENB(enb.eNodeB):

    REMOTE_DIR = '/osmo-gsm-tester-amarisoftenb'
    BINFILE = 'lteenb'
    CFGFILE = 'amarisoft_enb.cfg'
    CFGFILE_SIB1 = 'amarisoft_sib1.asn'
    CFGFILE_SIB23 = 'amarisoft_sib23.asn'
    CFGFILE_RF = 'amarisoft_rf_driver.cfg'
    CFGFILE_DRB = 'amarisoft_drb.cfg'
    LOGFILE = 'lteenb.log'

    def __init__(self, testenv, conf):
        super().__init__(testenv, conf, 'amarisoftenb')
        self.ue = None
        self.run_dir = None
        self.inst = None
        self._bin_prefix = None
        self.gen_conf = None
        self.config_file = None
        self.config_sib1_file = None
        self.config_sib23_file = None
        self.config_rf_file = None
        self.config_drb_file = None
        self.log_file = None
        self.process = None
        self.rem_host = None
        self.remote_inst = None
        self.remote_config_file =  None
        self.remote_config_sib1_file = None
        self.remote_config_sib23_file = None
        self.remote_config_rf_file = None
        self.remote_config_drb_file = None
        self.remote_log_file = None
        self.enable_measurements = False
        self.testenv = testenv
        if not rf_type_valid(conf.get('rf_dev_type', None)):
            raise log.Error('Invalid rf_dev_type=%s' % conf.get('rf_dev_type', None))

    def bin_prefix(self):
        if self._bin_prefix is None:
            self._bin_prefix = os.getenv('AMARISOFT_PATH_ENB', None)
            if self._bin_prefix == None:
                self._bin_prefix  = self.testenv.suite().trial().get_inst('amarisoftenb', self._run_node.run_label())
        return self._bin_prefix

    def cleanup(self):
        if self.process is None:
            return
        if self._run_node.is_local():
            return
        # copy back files (may not exist, for instance if there was an early error of process):
        try:
            self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file)
        except Exception as e:
            self.log(repr(e))

    def start(self, epc):
        self.log('Starting AmarisoftENB')
        self._epc = epc
        self.run_dir = util.Dir(self.testenv.test().get_run_dir().new_dir(self.name()))
        self.configure()
        self._start()

        # send t+Enter to enable console trace
        self.dbg('Enabling console trace')
        self.process.stdin_write('t\n')

    def _start(self):
        if self._run_node.is_local():
            env = { 'LD_LIBRARY_PATH': util.prepend_library_path(self.inst) }
            binary = self.inst.child('.', AmarisoftENB.BINFILE)
            self.dbg(run_dir=self.run_dir, binary=binary, env=env)
            args = (binary, os.path.abspath(self.config_file))
            self.process = process.Process(self.name(), self.run_dir, args, env=env)
        else:
            remote_env = { 'LD_LIBRARY_PATH': self.remote_inst }
            remote_binary = self.remote_inst.child('', AmarisoftENB.BINFILE)
            args = (remote_binary, self.remote_config_file)
            self.process = self.rem_host.RemoteProcess(AmarisoftENB.BINFILE, args, remote_env=remote_env)

        self.testenv.remember_to_stop(self.process)
        self.process.launch()

    def gen_conf_file(self, path, filename, values):
        self.dbg('AmarisoftENB ' + filename + ':\n' + pprint.pformat(values))
        with open(path, 'w') as f:
            r = template.render(filename, values)
            self.dbg(r)
            f.write(r)

    def configure(self):
        self.inst = util.Dir(os.path.abspath(self.bin_prefix()))
        if not self.inst.isfile('', AmarisoftENB.BINFILE):
            raise log.Error('No %s binary in' % AmarisoftENB.BINFILE, self.inst)

        self.config_file = self.run_dir.child(AmarisoftENB.CFGFILE)
        self.config_sib1_file = self.run_dir.child(AmarisoftENB.CFGFILE_SIB1)
        self.config_sib23_file = self.run_dir.child(AmarisoftENB.CFGFILE_SIB23)
        self.config_rf_file = self.run_dir.child(AmarisoftENB.CFGFILE_RF)
        self.config_drb_file = self.run_dir.child(AmarisoftENB.CFGFILE_DRB)
        self.log_file = self.run_dir.child(AmarisoftENB.LOGFILE)

        if not self._run_node.is_local():
            self.rem_host = remote.RemoteHost(self.run_dir, self._run_node.ssh_user(), self._run_node.ssh_addr())
            remote_prefix_dir = util.Dir(AmarisoftENB.REMOTE_DIR)
            self.remote_inst = util.Dir(remote_prefix_dir.child(os.path.basename(str(self.inst))))
            remote_run_dir = util.Dir(remote_prefix_dir.child(AmarisoftENB.BINFILE))

            self.remote_config_file = remote_run_dir.child(AmarisoftENB.CFGFILE)
            self.remote_config_sib1_file = remote_run_dir.child(AmarisoftENB.CFGFILE_SIB1)
            self.remote_config_sib23_file = remote_run_dir.child(AmarisoftENB.CFGFILE_SIB23)
            self.remote_config_rf_file = remote_run_dir.child(AmarisoftENB.CFGFILE_RF)
            self.remote_config_drb_file = remote_run_dir.child(AmarisoftENB.CFGFILE_DRB)
            self.remote_log_file = remote_run_dir.child(AmarisoftENB.LOGFILE)

        values = super().configure(['amarisoft', 'amarisoftenb'])

        # Convert parsed boolean string to Python boolean:
        self.enable_measurements = util.str2bool(values['enb'].get('enable_measurements', 'false'))
        config.overlay(values, dict(enb={'enable_measurements': self.enable_measurements}))

        # We need to set some specific variables programatically here to match IP addresses:
        if self._conf.get('rf_dev_type') == 'zmq':
            base_srate = self.num_prb2base_srate(self.num_prb())
            rf_dev_args = self.get_zmq_rf_dev_args()
            config.overlay(values, dict(enb=dict(sample_rate = base_srate / (1000*1000),
                                                 rf_dev_args = rf_dev_args)))

        # Set UHD frame size as a function of the cell bandwidth on B2XX
        if self._conf.get('rf_dev_type') == 'uhd' and values['enb'].get('rf_dev_args', None) is not None:
            if 'b200' in values['enb'].get('rf_dev_args'):
                rf_dev_args = values['enb'].get('rf_dev_args', '')
                rf_dev_args += ',' if rf_dev_args != '' and not rf_dev_args.endswith(',') else ''

                if self._num_prb < 25:
                    rf_dev_args += 'send_frame_size=512,recv_frame_size=512'
                elif self._num_prb == 25:
                    rf_dev_args += 'send_frame_size=1024,recv_frame_size=1024'
                elif self._num_prb > 25:
                    rf_dev_args += 'num_recv_frames=64,num_send_frames=64'

                if self._num_prb > 50:
                    # Reduce over the wire format to sc12
                    rf_dev_args += ',otw_format=sc12'

                config.overlay(values, dict(enb=dict(rf_dev_args=rf_dev_args)))

        logfile = self.log_file if self._run_node.is_local() else self.remote_log_file
        config.overlay(values, dict(enb=dict(log_filename=logfile)))

        # rf driver is shared between amarisoft enb and ue, so it has a
        # different cfg namespace 'trx'. Copy needed values over there:
        config.overlay(values, dict(trx=dict(rf_dev_type=values['enb'].get('rf_dev_type', None),
                                             rf_dev_args=values['enb'].get('rf_dev_args', None),
                                             rx_gain=values['enb'].get('rx_gain', None),
                                             tx_gain=values['enb'].get('tx_gain', None),
                                            )))

        self.gen_conf = values

        self.gen_conf_file(self.config_file, AmarisoftENB.CFGFILE, values)
        self.gen_conf_file(self.config_sib1_file, AmarisoftENB.CFGFILE_SIB1, values)
        self.gen_conf_file(self.config_sib23_file, AmarisoftENB.CFGFILE_SIB23, values)
        self.gen_conf_file(self.config_rf_file, AmarisoftENB.CFGFILE_RF, values)
        self.gen_conf_file(self.config_drb_file, AmarisoftENB.CFGFILE_DRB, values)

        if not self._run_node.is_local():
            self.rem_host.recreate_remote_dir(self.remote_inst)
            self.rem_host.scp('scp-inst-to-remote', str(self.inst), remote_prefix_dir)
            self.rem_host.recreate_remote_dir(remote_run_dir)
            self.rem_host.scp('scp-cfg-to-remote', self.config_file, self.remote_config_file)
            self.rem_host.scp('scp-cfg-sib1-to-remote', self.config_sib1_file, self.remote_config_sib1_file)
            self.rem_host.scp('scp-cfg-sib23-to-remote', self.config_sib23_file, self.remote_config_sib23_file)
            self.rem_host.scp('scp-cfg-rr-to-remote', self.config_rf_file, self.remote_config_rf_file)
            self.rem_host.scp('scp-cfg-drb-to-remote', self.config_drb_file, self.remote_config_drb_file)

    def ue_add(self, ue):
        if self.ue is not None:
            raise log.Error("More than one UE per ENB not yet supported (ZeroMQ)")
        self.ue = ue

    def running(self):
        return not self.process.terminated()

    def get_rfemu(self, cell=0, dl=True):
        cell_list = self.gen_conf['enb'].get('cell_list', None)
        if cell_list is None or len(cell_list) < cell + 1:
            raise log.Error('cell_list attribute or subitem not found!')
        rfemu_cfg = cell_list[cell].get('dl_rfemu', None)
        if rfemu_cfg is None: # craft amarisoft by default:
            rfemu_cfg = {'type': 'amarisoftctl',
                         'addr': self.addr(),
                         'ports': [9001]
                         }
        if rfemu_cfg['type'] == 'amarisoftctl': # this one requires extra config:
            config.overlay(rfemu_cfg, dict(cell_id=cell_list[cell]['cell_id']))
        rfemu_obj = rfemu.get_instance_by_type(rfemu_cfg['type'], rfemu_cfg)
        return rfemu_obj

    def ue_max_rate(self, downlink=True):
        # The max rate for a single UE per PRB configuration in TM1 with MCS 28 QAM64
        max_phy_rate_tm1_dl = { 6 : 3.2e6,
                               15 : 9.2e6,
                               25 : 18e6,
                               50 : 36e6,
                               75 : 55e6,
                               100 : 75e6 }
        max_phy_rate_tm1_ul = { 6 : 2.0e6,
                               15 : 5.1e6,
                               25 : 10e6,
                               50 : 21e6,
                               75 : 32e6,
                               100 : 51e6 }
        if downlink:
            max_rate = max_phy_rate_tm1_dl[self.num_prb()]
        else:
            max_rate = max_phy_rate_tm1_ul[self.num_prb()]

        # MIMO only supported for Downlink
        if downlink:
            if self._txmode > 2:
                max_rate *= 2
            # Lower max MCS for TM2 and above results in lower max rate
            if self._txmode >= 2 and self.num_prb() <= 25:
                max_rate *= 0.85

        return max_rate

# vim: expandtab tabstop=4 shiftwidth=4
