#!/usr/bin/env python

USAGE = """IOS device backup parsing

"""

import json
import sys

from darwinist.ios.backup import IOSDeviceBackups, IOSBackupError
from systematic.shell import Script, ScriptCommand

TIME_FORMAT = '%Y-%m-%dT%H:%M:%S'


class IOSBackupCommand(ScriptCommand):
    def parse_args(self, args):
        try:
            self.backups = IOSDeviceBackups()
        except IOSBackupError as e:
            self.exit(1, emsg)

        if 'names' in args and args.names:
            args.names = [v for n in args.names for v in n.split(',')]

        return args

    def filter_devices_by_name(self, args):
        if 'names' not in args or not args.names:
            return [device for device in self.backups]

        return [device for device in self.backups if device.device_name in args.names]


class ListBackupsCommand(IOSBackupCommand):
    def run(self, args):
        args = self.parse_args(args)

        for device in self.backups:
            self.message('{0} updated on {1}'.format(device.device_name, device.updated))


class CheckDatabasesCommand(IOSBackupCommand):
    def run(self, args):
        args = self.parse_args(args)

        for device in self.filter_devices_by_name(args):
            self.message('Checking {0}'.format(device))
            for key in ( 'sms', 'addressbook', 'notes', 'calendar', 'calls', ):
                db = getattr(device, key)
                if db.exists and db.readable:
                    self.message('  {0} OK'.format(db.name))
                else:
                    self.message('  {0} MISSING OR UNREADABLE'.format(db.name))


class DumpSMSCommand(IOSBackupCommand):
    def output_chat(self, fd, chat):
        for message in chat.messages:
            fd.write('%s %s %s\n' % (message.date, message.sender, message.text))
        fd.flush()

    def run(self, args):
        args = self.parse_args(args)

        for device in self.filter_devices_by_name(args):
            if not device.sms.exists:
                self.exit(2, 'No SMS backup for {0}'.format(device.device_name))

            if args.output_file:
                try:
                    fd = open(args.output_file, 'wb')
                except OSError as e:
                    self.exit(1, 'Error opening {0} for writing: {1}'.format(args.output_file, e))
                except IOError as e:
                    self.exit(1, 'Error opening {0} for writing: {1}'.format(args.output_file, e))

            else:
                fd = sys.stdout

            if args.json:
                data = {
                    'device': device.device_name,
                    'chats': []
                }
                for chat in device.sms.chats:
                    data['chats'].append({
                        'first': chat.first.date.strftime(TIME_FORMAT),
                        'last': chat.latest.date.strftime(TIME_FORMAT),
                        'messages': [
                            {
                                'date': message.date.strftime(TIME_FORMAT),
                                'sender': '{0}'.format(message.sender),
                                'text': message.text,
                            }
                            for message in chat.messages
                        ]
                    })
                fd.write(json.dumps(data, indent=2))
            else:
                for chat in device.sms.chats:
                    self.output_chat(fd, chat)


script = Script()
c = script.add_subcommand(ListBackupsCommand('list', 'List iOS device backups'))

c = script.add_subcommand(CheckDatabasesCommand('check', 'Check iOS device backup databases'))
c.add_argument('names', nargs='*', help='Device names to check')

c = script.add_subcommand(DumpSMSCommand('dump-sms', 'Dump SMS messages from iOS device backup'))
c.add_argument('-j', '--json', action='store_true', help='Output JSON')
c.add_argument('-o', '--output-file', help='Output file')
c.add_argument('names', nargs='*', help='Device names to check')


args = script.parse_args()

