# Copyright (c) 2010 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.

from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error

import dbus, dbus.mainloop.glib, gobject
import glib

from autotest_lib.client.cros import flimflam_test_path
from autotest_lib.client.cros.mainloop import ExceptionForwardingMainLoop
from autotest_lib.client.cros.mainloop import ExceptionForward
import flimflam, mm

class State:
    ENABLING = 0
    REGISTERING = 1
    CONNECTING = 2
    WAITING = 3
    DISCONNECTING = 4
    DISABLING = 5

class DormancyTester(ExceptionForwardingMainLoop):
    def __init__(self, loops, flim, device, *args, **kwargs):
        self.loopsleft = loops
        self.flim = flim
        self.device = device
        super(DormancyTester, self).__init__(
                *args, timeout_s=20 * loops + 20, **kwargs)

    def countdown(self):
        self.loopsleft -= 1
        print 'Countdown: %d' % (self.loopsleft,)
        if self.loopsleft == 0:
            self.quit()

    @ExceptionForward
    def enable(self):
        print 'Enabling...'
        self.state = State.ENABLING
        self.flim.EnableTechnology('cellular')

    @ExceptionForward
    def disable(self):
        print 'Disabling...'
        self.state = State.DISABLING
        self.flim.DisableTechnology('cellular')

    @ExceptionForward
    def connect(self):
        print 'Connecting...'
        self.state = State.CONNECTING
        self.flim.ConnectService(service=self.service, config_timeout=120)

    @ExceptionForward
    def disconnect(self):
        print 'Disconnecting...'
        self.state = State.DISCONNECTING
        self.flim.DisconnectService(service=self.service, wait_timeout=60)

    @ExceptionForward
    def PropertyChanged(self, *args, **kwargs):
        if args[0] == 'Powered':
            if not args[1]:
                self.HandleDisabled()
            else:
                self.HandleEnabled()
        elif args[0] == 'Connected':
            if not args[1]:
                self.HandleDisconnected()
            else:
                self.HandleConnected()
        elif args[0] == 'Services':
            self.CheckService()

    @ExceptionForward
    def DormancyStatus(self, *args, **kwargs):
        if args[0]:
            self.HandleDormant()
        else:
            self.HandleAwake()

    def FindService(self):
        self.service = self.flim.FindElementByPropertySubstring('Service',
                                                                'Type',
                                                                'cellular')

    def CheckService(self):
        self.FindService()
        if self.state == State.REGISTERING and self.service:
            self.HandleRegistered()

    def HandleDisabled(self):
        if self.state != State.DISABLING:
            raise error.TestFail('Disabled while not in state Disabling')
        print 'Disabled'
        self.countdown()
        self.enable()

    def HandleEnabled(self):
        if self.state != State.ENABLING:
            raise error.TestFail('Enabled while not in state Enabling')
        print 'Enabled'
        self.state = State.REGISTERING
        print 'Waiting for registration...'
        self.CheckService()

    def HandleRegistered(self):
        if self.state != State.REGISTERING:
            raise error.TestFail('Registered while not in state Registering')
        print 'Registered'
        self.connect()

    def HandleConnected(self):
        if self.state != State.CONNECTING:
            raise error.TestFail('Connected while not in state Connecting')
        print 'Connected'
        self.state = State.WAITING
        print 'Waiting for dormancy...'

    def HandleDormant(self):
        if self.state != State.WAITING:
            print 'Dormant while not in state Waiting; ignoring.'
            return
        print 'Dormant'
        self.disconnect()

    def HandleAwake(self):
        print 'Awake'

    def HandleDisconnected(self):
        if self.state != State.DISCONNECTING:
            raise error.TestFail(
                'Disconnected while not in state Disconnecting')
        print 'Disconnected'
        self.disable()

    def idle(self):
        connected = False
        powered = False

        device_props = self.device.GetProperties(utf8_strings = True)

        self.FindService()
        if self.service:
            service_props = self.service.GetProperties(utf8_strings = True)
            if service_props['State'] in ['online', 'portal', 'ready']:
                connected = True
            print 'Service exists, and state is %s.' % (service_props['State'],)
        else:
            print 'Service does not exist.'

        if device_props['Powered']:
            print 'Device is powered.'
            powered = True
        else:
            print 'Device is unpowered.'

        if powered and connected:
            print 'Starting with Disconnect.'
            self.disconnect()
        elif powered and (not connected):
            print 'Starting with Disable.'
            self.disable()
        elif (not powered) and (not connected):
            print 'Starting with Enable.'
            self.enable()
        else:
            raise error.TestFail('Service online but device unpowered!')



class network_3GDormancyDance(test.test):
    version = 1

    def FindModemPath(self):
        for modem in mm.EnumerateDevices():
            (obj, path) = modem
            try:
                if path.index('/org/chromium/ModemManager/Gobi') == 0:
                    return path
            except ValueError:
                pass
        return None

    def RequestDormancyEvents(self, modem_path):
        modem = dbus.Interface(
            self.bus.get_object('org.chromium.ModemManager', modem_path),
            dbus_interface='org.chromium.ModemManager.Modem.Gobi')
        modem.RequestEvents('+dormancy')

    def PropertyChanged(self, *args, **kwargs):
        self.tester.PropertyChanged(*args, **kwargs)

    def DormancyStatus(self, *args, **kwargs):
        self.tester.DormancyStatus(*args, **kwargs)

    def run_once(self, name='usb', loops=20, seed=None):
        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
        self.bus = dbus.SystemBus()

        main_loop = gobject.MainLoop()

        modem_path = self.FindModemPath()
        if not modem_path:
            raise error.TestFail('No Gobi modem found.')
        print 'Modem: %s' % (modem_path,)
        self.RequestDormancyEvents(modem_path)

        flim = flimflam.FlimFlam()
        device = flim.FindElementByNameSubstring('Device', name)

        if not device:
            device = flim.FindElementByPropertySubstring('Device',
                                                         'Interface',
                                                          name)
        self.bus.add_signal_receiver(self.PropertyChanged,
                                     signal_name='PropertyChanged')
        self.bus.add_signal_receiver(self.DormancyStatus,
                                     signal_name='DormancyStatus')
        self.tester = DormancyTester(main_loop=main_loop,
                                     loops=loops, flim=flim, device=device)
        self.tester.run()
