# osmo_gsm_tester: specifics for running an osmocon
#
# Copyright (C) 2018 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 tempfile

from .core import log, util, process
from .core.event_loop import MainLoop

class Osmocon(log.Origin):

    FIRMWARE_FILE="opt/osmocom-bb/target/firmware/board/compal_e88/layer1.compalram.bin"

    def __init__(self, suite_run, conf):
        serial_device = conf.get('serial_device')
        if serial_device is None:
            raise log.Error('osmocon_phone contains no attr "serial_device"')
        self.serial_device = os.path.realpath(serial_device)
        super().__init__(log.C_RUN, 'osmocon_%s' % os.path.basename(self.serial_device))
        self.run_dir = None
        self.process = None
        self.suite_run = suite_run
        self.conf = conf
        self.sk_tmp_dir = tempfile.mkdtemp('', 'ogtosmoconsk')
        if len(self.l2_socket_path().encode()) > 107:
            raise log.Error('Path for l2 socket is longer than max allowed len for unix socket path (107):', self.l2_socket_path())
        if len(self.loader_socket_path().encode()) > 107:
            raise log.Error('Path for loader socket is longer than max allowed len for unix socket path (107):', self.loader_socket_path())

    def l2_socket_path(self):
        return os.path.join(self.sk_tmp_dir, 'osmocom_l2')

    def loader_socket_path(self):
        return os.path.join(self.sk_tmp_dir, 'osmocom_loader')

    def start(self):
        self.log('Resetting the phone')
        # TODO: make sure the pone is powered off before starting osmocon

        self.log('Starting osmocon')
        self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))

        inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('osmocom-bb')))

        binary = inst.child('sbin', 'osmocon')
        if not os.path.isfile(binary):
            raise RuntimeError('Binary missing: %r' % binary)
        lib = inst.child('lib')
        if not os.path.isdir(lib):
            raise RuntimeError('No lib/ in %r' % inst)

        env = { 'LD_LIBRARY_PATH': util.prepend_library_path(lib) }

        firmware_path = os.path.join(str(inst), Osmocon.FIRMWARE_FILE)
        if not os.path.isfile(firmware_path):
            raise RuntimeError('Binary missing: %r' % firmware_path)
        self.dbg(run_dir=self.run_dir, binary=binary, env=env)
        self.process = process.Process(self.name(), self.run_dir,
                                       (binary, '-p', self.serial_device,
                                       '-m', 'c123xor',
                                       '-s', self.l2_socket_path(),
                                       '-l', self.loader_socket_path(),
                                        firmware_path),
                                       env=env)
        self.suite_run.remember_to_stop(self.process)
        self.process.launch()
        self.log('Waiting for osmocon to be up and running')
        MainLoop.wait(self, os.path.exists, self.l2_socket_path())

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

    def cleanup(self):
        if self.sk_tmp_dir:
            try:
                os.remove(self.l2_socket_path())
            except OSError:
                pass
            try:
                os.remove(self.loader_socket_path())
            except OSError:
                pass
            os.rmdir(self.sk_tmp_dir)

# vim: expandtab tabstop=4 shiftwidth=4
