#!/usr/bin/python2
# 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.

import dbus, logging
from autotest_lib.client.common_lib import error

sample = {
    'pdu' :
      '07914140540510F0040B916171056429F500001190804181106904D4F29C0E',
    'parsed' :
      {'text' : 'Test',
       'number' : '+16175046925',
       'timestamp' : '110908141801-04',
       'smsc' : '+14044550010'
       }
    }

sample_multipart = {
    'pdu' :
      ['07912160130320F8440B916171056429F5000011909161037469A0050003920201A9'
       'E5391DF43683E6EF7619C47EBBCF207A194F0789EB74D03D4D47BFEB7450D89D0791'
       'D366737A5C67D3416374581E1ED3CBF23928ED1EB3EBE43219947683E8E832A85D9E'
       'CFC3E7B20B4445A7E72077B94C9E83E86F90B80C7ADBCB72101D5D06B1CBEE331D0D'
       'A2A3E5E539FACD2683CC6F39888E2E83D8EF71980D9ABFCDF47B585E06D1DF',
       '07912160130320F5440B916171056429F50000119091610384691505000392020241'
       'E437888E2E83E670769AEE02'],
    'parsed' :
      {'text' : 'Test of some long text but without any difficult characters'
       ' included in the message. This needs to be over the length threshold'
       ' for the local software to do the split.',
       'number' : '+16175046925',
       'timestamp' : '110919163047-04',
       'smsc' : '+12063130028'
       }
    }


class SmsStore(object):
    '''SMS content management - this maintains an internal model of the
    index->PDU mapping that the fakemodem program should be returning so
    that tests can add and remove individual PDUs and handles generating
    the correct set of responses, including the complete SMS list.
    '''

    def __init__(self, fakemodem):
        self.fakemodem = fakemodem
        self.smsdict = {}
        self.fakemodem.SetResponse('\+CMGR=', '', '+CMS ERROR: 321')
        self.fakemodem.SetResponse('\+CMGD=', '', '+CMS ERROR: 321')
        self._sms_regen_list()

    def sms_insert(self, index, pdu):
        '''Add a SMS to the fake modem's list.'''
        smsc_len = int(pdu[0:1], 16)
        mlen = len(pdu)/2 - smsc_len - 1

        self.fakemodem.RemoveResponse('\+CMGD=')
        self.fakemodem.RemoveResponse('\+CMGR=')
        self.fakemodem.SetResponse('\+CMGD=%d' % (index), '', '')
        self.fakemodem.SetResponse('\+CMGR=%d' % (index),
                                   '+CMGR: 1,,%d\r\n%s' % (mlen, pdu), '')
        self.fakemodem.SetResponse('\+CMGR=', '', '+CMS ERROR: 321')
        self.fakemodem.SetResponse('\+CMGD=', '', '+CMS ERROR: 321')

        self.smsdict[index] = pdu
        self._sms_regen_list()

    def sms_receive(self, index, pdu):
        '''Add a SMS to the fake modem's list, like sms_insert(), and generate
        an unsolicited new-sms message.'''
        self.sms_insert(index, pdu)
        self.fakemodem.SendUnsolicited('+CMTI: "ME",%d'%(index))

    def sms_remove(self, index):
        '''Remove a SMS from the fake modem's list'''
        self.fakemodem.RemoveResponse('\+CMGR=%d' % (index))
        self.fakemodem.RemoveResponse('\+CMGD=%d' % (index))
        del self.smsdict[index]
        self._sms_regen_list()

    def _sms_regen_list(self):
        response = ''
        keys = self.smsdict.keys()
        keys.sort()
        for i in keys:
            pdu = self.smsdict[i]
            smsc_len = int(pdu[0:1],16)
            mlen = len(pdu)/2 - smsc_len - 1
            response = response + '+CMGL: %d,1,,%d\r\n%s\r\n' % (i, mlen, pdu)
        self.fakemodem.SetResponse('\+CMGL=4', response, '')


class SmsTest(object):
    def __init__(self, gsmsms):
        self.gsmsms = gsmsms

    def compare(self, expected, got):
        '''Compare two SMS dictionaries, discounting the index number if
        not specified in the first.'''
        if expected == got:
            return True
        if 'index' in expected:
            return False
        if 'index' not in got:
            return False
        got = dict(got)
        del got['index']
        return expected == got

    def compare_list(self, expected_list, got_list):
        if len(expected_list) != len(got_list):
            return False
        # There must be a more Pythonic way to do this
        for (expected,got) in zip(expected_list, got_list):
            if self.compare(expected, got) == False:
                return False
        return True

    def test_get(self, index, expected):
        try:
            sms = self.gsmsms.Get(index)
        except dbus.DBusException, db:
            if expected is not None:
                raise
            return

        if expected is None:
            logging.info('Got %s' % sms)
            raise error.TestFail('SMS.Get(%d) succeeded unexpectedly' %
                                 index)
        if self.compare(expected, sms) == False:
            logging.info('Got %s, expected %s' % (sms, expected))
            raise error.TestFail('SMS.Get(%d) did not match expected values' %
                                 index)

    def test_delete(self, index, expected_success):
        try:
            self.gsmsms.Delete(index)
            if expected_success == False:
                raise error.TestFail('SMS.Delete(%d) succeeded unexpectedly' %
                                     index)
        except dbus.DBusException, db:
            if expected_success:
                raise

    def test_list(self, expected_list):
        sms_list = self.gsmsms.List()
        if self.compare_list(expected_list, sms_list) == False:
            logging.info('Got %s, expected %s' % (sms_list, expected_list))
            raise error.TestFail('SMS.List() did not match expected values')

    def test_has_none(self):
        '''Test that the SMS interface has no messages.'''
        self.test_list([])
        self.test_get(1, None)
        self.test_delete(1, False)
        self.test_delete(2, False)

    def test_has_one(self, parsed_sms):
        '''Test that the SMS interface has exactly one message at index 1
        As a side effect, deletes the message.'''
        self.test_list([parsed_sms])
        self.test_get(1, parsed_sms)
        self.test_get(2, None)
        self.test_delete(2, False)
        self.test_delete(1, True)
