#!/usr/bin/env python2
# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This module is the entry point for pseudomodem. Though honestly, I can't think
# of any case when you want to use this module directly. Instead, use the
# |pseudomodem_context| module that provides a way to launch pseudomodem in a
# child process.

import argparse
import dbus
import dbus.mainloop.glib
import gobject
import imp
import json
import logging
import os
import os.path
import signal
import sys
import testing
import traceback

import logging_setup
import modem_cdma
import modem_3gpp
import modemmanager
import sim
import state_machine_factory as smf

import common
from autotest_lib.client.cros.cellular import mm1_constants

# Flags used by pseudomodem modules only that are defined below in
# ParserArguments.
CLI_FLAG = '--cli'
EXIT_ERROR_FILE_FLAG = '--exit-error-file'

class PseudoModemManager(object):
    """
    The main class to be used to launch the pseudomodem.

    There should be only one instance of this class that orchestrates
    pseudomodem.

    """

    def Setup(self, opts):
        """
        Call |Setup| to prepare pseudomodem to be launched.

        @param opts: The options accepted by pseudomodem. See top level function
                |ParseArguments| for details.

        """
        self._opts = opts

        self._in_exit_sequence = False
        self._manager = None
        self._modem = None
        self._state_machine_factory = None
        self._sim = None
        self._mainloop = None

        self._dbus_loop = dbus.mainloop.glib.DBusGMainLoop()
        self._bus = dbus.SystemBus(private=True, mainloop=self._dbus_loop)
        self._bus_name = dbus.service.BusName(mm1_constants.I_MODEM_MANAGER,
                                              self._bus)
        logging.info('Exported dbus service with well known name: |%s|',
                     self._bus_name.get_name())

        self._SetupPseudomodemParts()
        logging.info('Pseudomodem setup completed!')


    def StartBlocking(self):
        """
        Start pseudomodem operation.

        This call blocks untill |GracefulExit| is called from some other
        context.

        """
        self._mainloop = gobject.MainLoop()
        self._mainloop.run()


    def GracefulExit(self):
        """ Stop pseudomodem operation and clean up. """
        if self._in_exit_sequence:
            logging.debug('Already exiting.')
            return

        self._in_exit_sequence = True
        logging.info('pseudomodem shutdown sequence initiated...')
        # Guard each step by its own try...catch, because we want to attempt
        # each step irrespective of whether the earlier ones succeeded.
        try:
            if self._manager:
                self._manager.Remove(self._modem)
        except Exception as e:
            logging.warning('Error while exiting: %s', repr(e))
        try:
            if self._mainloop:
                self._mainloop.quit()
        except Exception as e:
            logging.warning('Error while exiting: %s', repr(e))

        logging.info('pseudomodem: Bye! Bye!')


    def _SetupPseudomodemParts(self):
        """
        Contructs all pseudomodem objects, but does not start operation.

        Three main objects are created: the |Modem|, the |Sim|, and the
        |StateMachineFactory|. This objects may be instantiations of the default
        classes, or of user provided classes, depending on options provided.

        """
        self._ReadCustomParts()

        use_3gpp = (self._opts.family == '3GPP')

        if not self._modem and not self._state_machine_factory:
            self._state_machine_factory = smf.StateMachineFactory()
            logging.info('Created default state machine factory.')

        if use_3gpp and not self._sim:
            self._sim = sim.SIM(sim.SIM.Carrier('test'),
                                mm1_constants.MM_MODEM_ACCESS_TECHNOLOGY_GSM,
                                locked=self._opts.locked)
            logging.info('Created default 3GPP SIM.')

        # Store this constant here because the variable name is too long.
        network_available = dbus.types.UInt32(
                mm1_constants.MM_MODEM_3GPP_NETWORK_AVAILABILITY_AVAILABLE)
        if not self._modem:
            if use_3gpp:
                technology_gsm = dbus.types.UInt32(
                        mm1_constants.MM_MODEM_ACCESS_TECHNOLOGY_GSM)
                networks = [modem_3gpp.Modem3gpp.GsmNetwork(
                        'Roaming Network Long ' + str(i),
                        'Roaming Network Short ' + str(i),
                        '00100' + str(i + 1),
                        network_available,
                        technology_gsm)
                        for i in xrange(self._opts.roaming_networks)]
                # TODO(armansito): Support "not activated" initialization option
                # for 3GPP carriers.
                self._modem = modem_3gpp.Modem3gpp(
                        self._state_machine_factory,
                        roaming_networks=networks)
                logging.info('Created default 3GPP modem.')
            else:
                self._modem = modem_cdma.ModemCdma(
                        self._state_machine_factory,
                        modem_cdma.ModemCdma.CdmaNetwork(
                                activated=self._opts.activated))
                logging.info('Created default CDMA modem.')

        # Everyone gets the |_bus|, woohoo!
        self._manager = modemmanager.ModemManager(self._bus)
        self._modem.SetBus(self._bus)  # Also sets it on StateMachineFactory.
        self._manager.Add(self._modem)

        # Unfortunately, setting the SIM has to be deferred until everyone has
        # their BUS set. |self._sim| exists if the user provided one, or if the
        # modem family is |3GPP|.
        if self._sim:
            self._modem.SetSIM(self._sim)

        # The testing interface can be brought up now that we have the bus.
        self._testing_object = testing.Testing(self._modem, self._bus)


    def _ReadCustomParts(self):
        """
        Loads user provided implementations of pseudomodem objects.

        The user can provide their own implementations of the |Modem|, |Sim| or
        |StateMachineFactory| classes.

        """
        if not self._opts.test_module:
            return

        test_module = self._LoadCustomPartsModule(self._opts.test_module)

        if self._opts.test_modem_class:
            self._modem = self._CreateCustomObject(test_module,
                                                   self._opts.test_modem_class,
                                                   self._opts.test_modem_arg)

        if self._opts.test_sim_class:
            self._sim = self._CreateCustomObject(test_module,
                                                 self._opts.test_sim_class,
                                                 self._opts.test_sim_arg)

        if self._opts.test_state_machine_factory_class:
            if self._opts.test_modem_class:
                logging.warning(
                        'User provided a |Modem| implementation as well as a '
                        '|StateMachineFactory|. Ignoring the latter.')
            else:
                self._state_machine_factory = self._CreateCustomObject(
                        test_module,
                        self._opts.test_state_machine_factory_class,
                        self._opts.test_state_machine_factory_arg)


    def _CreateCustomObject(self, test_module, class_name, arg_file_name):
        """
        Create the custom object specified by test.

        @param test_module: The loaded module that implemets the custom object.
        @param class_name: Name of the class implementing the custom object.
        @param arg_file_name: Absolute path to file containing list of arguments
                taken by |test_module|.|class_name| constructor in json.
        @returns: A brand new object of the custom type.
        @raises: AttributeError if the class definition is not found;
                ValueError if |arg_file| does not contain valid json
                representaiton of a python list.
                Other errors may be raised during object creation.

        """
        arg = None
        if arg_file_name:
            arg_file = open(arg_file_name, 'rb')
            try:
                arg = json.load(arg_file)
            finally:
                arg_file.close()
            if not isinstance(arg, list):
                raise ValueError('Argument must be a python list.')

        class_def = getattr(test_module, class_name)
        try:
            if arg:
                logging.debug('Loading test class %s%s',
                              class_name, str(arg))
                return class_def(*arg)
            else:
                logging.debug('Loading test class %s', class_def)
                return class_def()
        except Exception as e:
            logging.error('Exception raised when instantiating class %s: %s',
                          class_name, str(e))
            raise


    def _LoadCustomPartsModule(self, module_abs_path):
        """
        Loads the given file as a python module.

        The loaded module *is* added to |sys.modules|.

        @param module_abs_path: Absolute path to the file to be loaded.
        @returns: The loaded module.
        @raises: ImportError if the module can not be loaded, or if another
                 module with the same name is already loaded.

        """
        path, name = os.path.split(module_abs_path)
        name, _ = os.path.splitext(name)

        if name in sys.modules:
            raise ImportError('A module named |%s| is already loaded.' %
                              name)

        logging.debug('Loading module %s from %s', name, path)
        module_file, filepath, data = imp.find_module(name, [path])
        try:
            module = imp.load_module(name, module_file, filepath, data)
        except Exception as e:
            logging.error(
                    'Exception raised when loading test module from %s: %s',
                    module_abs_path, str(e))
            raise
        finally:
            module_file.close()
        return module


# ##############################################################################
# Public static functions.
def ParseArguments(arg_string=None):
    """
    The main argument parser.

    Pseudomodem is a command line tool.
    Since pseudomodem is a highly customizable tool, the command line arguments
    are expected to be quite complex.
    We use argparse to keep the command line options easy to use.

    @param arg_string: If not None, the string to parse. If none, |sys.argv| is
            used to obtain the argument string.
    @returns: The parsed options object.

    """
    parser = argparse.ArgumentParser(
            description="Run pseudomodem to simulate a modem using the "
                        "modemmanager-next DBus interface.")

    parser.add_argument(
            CLI_FLAG,
            action='store_true',
            default=False,
            help='Launch the command line interface in foreground to interact '
                 'with the launched pseudomodem process. This argument is used '
                 'by |pseudomodem_context|. pseudomodem itself ignores it.')
    parser.add_argument(
            EXIT_ERROR_FILE_FLAG,
            default=None,
            help='If provided, full path to file to which pseudomodem should '
                 'dump the error condition before exiting, in case of a crash. '
                 'The file is not created if it does not already exist.')

    modem_arguments = parser.add_argument_group(
            title='Modem options',
            description='Options to customize the modem exported.')
    modem_arguments.add_argument(
            '--family', '-f',
            choices=['3GPP', 'CDMA'],
            default='3GPP')

    gsm_arguments = parser.add_argument_group(
            title='3GPP options',
            description='Options specific to 3GPP modems. [Only make sense '
                        'when modem family is 3GPP]')

    gsm_arguments.add_argument(
            '--roaming-networks', '-r',
            type=_NonNegInt,
            default=0,
            metavar='<# networks>',
            help='Number of roaming networks available')

    cdma_arguments = parser.add_argument_group(
            title='CDMA options',
            description='Options specific to CDMA modems. [Only make sense '
                        'when modem family is CDMA]')

    sim_arguments = parser.add_argument_group(
            title='SIM options',
            description='Options to customize the SIM in the modem. [Only make '
                        'sense when modem family is 3GPP]')
    sim_arguments.add_argument(
            '--activated',
            type=bool,
            default=True,
            help='Determine whether the SIM is activated')
    sim_arguments.add_argument(
            '--locked', '-l',
            type=bool,
            default=False,
            help='Determine whether the SIM is in locked state')

    testing_arguments = parser.add_argument_group(
            title='Testing interface options',
            description='Options to modify how the tests or user interacts '
                        'with pseudomodem')
    testing_arguments = parser.add_argument(
            '--interactive-state-machines-all',
            type=bool,
            default=False,
            help='Launch all state machines in interactive mode.')
    testing_arguments = parser.add_argument(
            '--interactive-state-machine',
            type=str,
            default=None,
            help='Launch the specified state machine in interactive mode. May '
                 'be repeated to specify multiple machines.')

    customize_arguments = parser.add_argument_group(
            title='Customizable modem options',
            description='Options to customize the emulated modem.')
    customize_arguments.add_argument(
            '--test-module',
            type=str,
            default=None,
            metavar='CUSTOM_MODULE',
            help='Absolute path to the module with custom definitions.')
    customize_arguments.add_argument(
            '--test-modem-class',
            type=str,
            default=None,
            metavar='MODEM_CLASS',
            help='Name of the class in CUSTOM_MODULE that implements the modem '
                 'to load.')
    customize_arguments.add_argument(
            '--test-modem-arg',
            type=str,
            default=None,
            help='Absolute path to the json description of argument list '
                 'taken by MODEM_CLASS.')
    customize_arguments.add_argument(
            '--test-sim-class',
            type=str,
            default=None,
            metavar='SIM_CLASS',
            help='Name of the class in CUSTOM_MODULE that implements the SIM '
                 'to load.')
    customize_arguments.add_argument(
            '--test-sim-arg',
            type=str,
            default=None,
            help='Aboslute path to the json description of argument list '
                 'taken by SIM_CLASS')
    customize_arguments.add_argument(
            '--test-state-machine-factory-class',
            type=str,
            default=None,
            metavar='SMF_CLASS',
            help='Name of the class in CUSTOM_MODULE that impelements the '
                 'state machine factory to load. Only used if MODEM_CLASS is '
                 'not provided.')
    customize_arguments.add_argument(
            '--test-state-machine-factory-arg',
            type=str,
            default=None,
            help='Absolute path to the json description of argument list '
                 'taken by SMF_CLASS')

    opts = parser.parse_args(arg_string)

    # Extra sanity checks.
    if opts.family == 'CDMA' and opts.roaming_networks > 0:
        raise argparse.ArgumentTypeError('CDMA networks do not support '
                                         'roaming networks.')

    test_objects = (opts.test_modem_class or
                    opts.test_sim_class or
                    opts.test_state_machine_factory_class)
    if not opts.test_module and test_objects:
        raise argparse.ArgumentTypeError('test_module is required with any '
                                         'other customization arguments.')

    if opts.test_modem_class and opts.test_state_machine_factory_class:
        logging.warning('test-state-machine-factory-class will be ignored '
                        'because test-modem-class was provided.')

    return opts


def ExtractExitError(dump_file_path):
    """
    Gets the exit error left behind by a crashed pseudomodem.

    If there is a file at |dump_file_path|, extracts the error and the traceback
    left behind by the child process. This function is intended to be used by
    the launching process to parse the error file left behind by pseudomodem.

    @param dump_file_path: Full path to the file to read.
    @returns: (error_reason, error_traceback)
            error_reason: str. The one line reason for error that should be
                    used to raise exceptions.
            error_traceback: A list of str. This is the traceback left
                    behind by the child process, if any. May be [].

    """
    error_reason = 'No detailed reason found :('
    error_traceback = []
    if dump_file_path:
        try:
            dump_file = open(dump_file_path, 'rb')
            error_reason = dump_file.readline().strip()
            error_traceback = dump_file.readlines()
            dump_file.close()
        except OSError as e:
            logging.error('Could not open dump file %s: %s',
                          dump_file_path, str(e))
    return error_reason, error_traceback


# The single global instance of PseudoModemManager.
_pseudo_modem_manager = None


# ##############################################################################
# Private static functions.
def _NonNegInt(value):
    value = int(value)
    if value < 0:
        raise argparse.ArgumentTypeError('%s is not a non-negative int' % value)
    return value


def _DumpExitError(dump_file_path, exc):
    """
    Dump information about the raised exception in the exit error file.

    Format of file dumped:
    - First line is the reason for the crash.
    - Subsequent lines are the traceback from the exception raised.

    We expect the file to exist, because we want the launching context (that
    will eventually read the error dump) to create and own the file.

    @param dump_file_path: Full path to file to which we should dump.
    @param exc: The exception raised.

    """
    if not dump_file_path:
        return

    if not os.path.isfile(dump_file_path):
        logging.error('File |%s| does not exist. Can not dump exit error.',
                      dump_file_path)
        return

    try:
        dump_file = open(dump_file_path, 'wb')
    except IOError as e:
        logging.error('Could not open file |%s| to dump exit error. '
                      'Exception raised when opening file: %s',
                      dump_file_path, str(e))
        return

    dump_file.write(str(exc) + '\n')
    dump_file.writelines(traceback.format_exc())
    dump_file.close()


def sig_handler(signum, frame):
    """
    Top level signal handler to handle user interrupt.

    @param signum: The signal received.
    @param frame: Ignored.
    """
    global _pseudo_modem_manager
    logging.debug('Signal handler called with signal %d', signum)
    if _pseudo_modem_manager:
        _pseudo_modem_manager.GracefulExit()


def main():
    """
    This is the entry point for raw pseudomodem.

    You should not be running this module as a script. If you're trying to run
    pseudomodem from the command line, see |pseudomodem_context| module.

    """
    global _pseudo_modem_manager

    logging_setup.SetupLogging()

    logging.info('Pseudomodem commandline: [%s]', str(sys.argv))
    opts = ParseArguments()

    signal.signal(signal.SIGINT, sig_handler)
    signal.signal(signal.SIGTERM, sig_handler)

    try:
        _pseudo_modem_manager = PseudoModemManager()
        _pseudo_modem_manager.Setup(opts)
        _pseudo_modem_manager.StartBlocking()
    except Exception as e:
        logging.error('Caught exception at top level: %s', str(e))
        _DumpExitError(opts.exit_error_file, e)
        _pseudo_modem_manager.GracefulExit()
        raise


if __name__ == '__main__':
    main()
