#!/usr/bin/python

# Copyright (c) 2011 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.
#
# Implement a pseudo gsm modem.
#
# This modem mimics a GSM modem and allows a user test shill, flimflam
# and UI behaviors when a supported SIM is inserted into the device.
#
# Flimflam Testing
# ================
# To test when running flimflam you can either use an extra ethernet
# port as the pseudo modem network interface, you you create a virtual
# interface.
#
# To use eth0 as your pseudo modem rename it pseudo-modem0:
#   # backchannel setup eth0 pseudo-modem0
#
# and then run the fake modem program:
#   # fake-gsm-modem tmobile
#
# When done, clean up with:
#   # backchannel teardown eth0 pseudo-modem0
#
# Alternatively, you can create a virtual interface which will not
# route packets anywhere, but will allow dhcp to succeed:
#   # ip link add name pseudo-modem0 type veth peer name pseudomodem0p
#
# When done, clean up with:
#   # ip link del pseudo-modem0
#
# Shill Testing
# ================
# To test when running shill, create a virtual interface called
# pseudomodem0:
#
#   # veth pseudomodem0 172.16.1
#
# then run the fake modem program:
#   # fake-gsm-modem -c tmobile --shill --smscount 3 --sms_signal 5
#
# which will start the fake GSM modem and cause shill to receive 3 new SMS notifications.
# Don't pass --smscount and --sms_signal, if you don't want to simulate SMS.
#
# when done, clean up with:
#   # veth teardown pseudomodem0
#

import glib
import gobject
from optparse import OptionParser
import os
import string
import sys

import dbus
import dbus.mainloop.glib


import_path = os.environ.get('SYSROOT', '/usr/local') + '/usr/lib/flimflam/test'
sys.path.append(import_path)

import flimflam_test
GSM_Modem = flimflam_test.GSM_Modem
ModemManager = flimflam_test.ModemManager
SIM = flimflam_test.SIM

DEFAULT_CARRIER = 'att'

# A list of the supported carriers.
SIM_LIST = {
    # Format for adding sims to the dictionary:
    # <Carrier_Name> : SIM( mcc_country = <country>,
    #                       mnc = <MNC>,
    #                       operator_name = <operator name>,
    #                       msin = <MSIN>,
    #                       mcc = <MCC>
    #
    # MCC value is favored over the mcc_country if both are
    # provided.
    'att'       : SIM('us', '090', 'AT&T'),
    'tmobile'   : SIM('us', '026', 'T-Mobile'),
    'simyo'     : SIM('de', '03', 'simyo'),
    'movistar'  : SIM('es', '07', 'Movistar'),
    'sfr'       : SIM('fr', '10', 'SFR'),
    'three'     : SIM('gb', '20', '3'),
    'threeita'  : SIM('it', '99', '3ITA'),
    'kpn'       : SIM('nl', '08', 'KPN'),
}

def make_sms(index, text):
    return {
        'index': index,
        'text' : text or 'Test SMS at %s' % index,
        'number' : '+16175046925',
        'timestamp' : '110919163047-04',
        'smsc' : '+12063130028'
        }

def main():

    usage = '''
Run fake-gsm-modem to simulate a gsm modem with different sims.
This can be used to simpilify the verification process of UI features
that use overseas sims.

To Use:
    1) Device should be read/write and running a test image.
    2) sudo mv /etc/init/cromo.conf
    3) Reboot Device
    4) Connect device using ethernet port and obtain <eth interface name>
    5) cd /usr/local/lib/flimflam/test
    6) ./backchannel setup <eth iface name> pseudo-modem0
    7) ./fake-gsm-modem [--carrier=<carrier name>] &
'''

    parser = OptionParser(usage=usage)
    parser.add_option('-c', '--carrier', dest='carrier_name',
                      metavar='<carrier name>',
                      help='<carrier name> := att | tmobile | simyo | '
                           'movistar | sfr | three | threeita | kpn')
    parser.add_option('-s', '--smscount', dest='sms_count',
                      default=0,
                      metavar='<smscount>',
                      help='<smscount> := integer')
    parser.add_option('-S', '--sms_signal', dest='sms_signal',
                      default=0,
                      metavar='<delay>',
                      help='<delay> := integer number of seconds')
    parser.add_option('-t', '--text', dest='sms_text',
                      default=None,
                      metavar='<text>',
                      help='<text> := text for sms messages')
    parser.add_option('-f', '--file', dest='filename',
                      default=None,
                      metavar='<filename>',
                      help='<filename> := file with text for sms messages')
    parser.add_option('-i', '--shill', dest='shill',
                      default=False,
                      action="store_true",
                      help='use shill device names instead of flimflam names.')

    (options, args) = parser.parse_args()

    if not options.carrier_name:
        options.carrier_name = DEFAULT_CARRIER

    sim_card = SIM_LIST[string.lower(options.carrier_name)]

    smses = {}
    if options.filename:
        f = open(options.filename, 'r')
        for index, line in enumerate(f.readlines()):
            line = line.strip()
            if line:
                smses[index] = make_sms(index, line)
    else:
        for index in xrange(int(options.sms_count)):
            smses[index] = make_sms(index, options.sms_text)

    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
    bus = dbus.SystemBus()
    name = dbus.service.BusName(flimflam_test.CMM, bus)
    manager = ModemManager(bus, flimflam_test.OCMM)
    device = 'pseudo-modem0'
    if options.shill:
        device = 'pseudomodem0'
    if options.sms_signal == 0:
        initial_smses = smses
    else:
        initial_smses = {}

    testmodem0 = GSM_Modem(manager, '/TestModem/0', gsm_sim=sim_card,
                           smses=initial_smses, device=device)

    if options.sms_signal:
        def AddSmses():
            for sms in smses.values():
                testmodem0.AddSMS(sms)
        glib.timeout_add(1000*int(options.sms_signal), AddSmses)

    mainloop = gobject.MainLoop()
    print "Running test modemmanager."
    mainloop.run()

if __name__ == '__main__':
    main()
