# pywurfl - Wireless Universal Resource File Tools in Python
# Copyright (C) 2006-2009 Armand Lynch
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation; either version 2.1 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this library; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Armand Lynch <lyncha@users.sourceforge.net>

__doc__ = \
"""
pywurfl WURFL class hierarchy serializer
"""

from time import ctime

try:
    from xml.etree.ElementTree import ElementTree, Element, SubElement
except ImportError:
    try:
        from cElementTree import ElementTree, Element, SubElement
    except ImportError:
        from elementtree.ElementTree import ElementTree, Element, SubElement

from pywurfl import __version__ as pw_version
from pywurfl.exceptions import WURFLException


__author__ = "Armand Lynch <lyncha@users.sourceforge.net>"
__copyright__ = "Copyright 2006-2009, Armand Lynch"
__license__ = "LGPL"
__url__ = "http://celljam.net/"
__all__ = ['Serialize']


class Serialize(object):
    def __init__(self, devices):
        self.root_device = devices.select_id('generic', instance=False)
        self.common_caps = ['actual_device_root', 'children', 'devid', 'devua',
                            'groups', 'fall_back']
        self.cap_groups = {}

    def _find_group(self, cap):
        group = self.cap_groups.get(cap)
        if group is None:
            for group in self.root_device.groups:
                if cap in self.root_device.groups[group]:
                    self.cap_groups[cap] = group
                    return group
            else:
                msg = "'%s' capability does not belong to a generic group"
                raise WURFLException(msg % cap)
        return group

    def _get_value(self, x):
        if isinstance(x, bool):
            if x:
                return "true"
            else:
                return "false"
        if isinstance(x, (int, float, long)):
            return str(x)
        return x

    def _walk(self, device, devices):
        new_dev = SubElement(devices, 'device')
        new_dev.set('fall_back', device.fall_back)
        new_dev.set('id', device.devid)
        new_dev.set('user_agent', device.devua)
        if device.actual_device_root:
            new_dev.set('actual_device_root', 'true')

        groups = {}
        for cap in (c for c in device.__dict__ if c not in self.common_caps and
                    not c.startswith('_')):
            value = self._get_value(getattr(device, cap))
            try:
                groups[self._find_group(cap)].append((cap, value))
            except (AttributeError, KeyError):
                groups[self._find_group(cap)] = [(cap, value)]


        for group in groups:
            new_group = SubElement(new_dev, 'group')
            new_group.set('id', group)
            for cap, value in groups[group]:
                new_cap = SubElement(new_group, 'capability')
                new_cap.set('name', cap)
                new_cap.set('value', value)

        for child in device.children:
            self._walk(child, devices)

    def to_xml(self, filename):
        """
        Serialize pywurfl's WURFL class hierarchy to xml

        @param filename: The filename to save the hierarchy to
        @type filename: string
        """

        root = Element('wurfl')
        version = SubElement(root, 'version')
        ver = SubElement(version, 'ver')
        ver.text = "Generated by pywurfl v%s" % pw_version
        last_updated = SubElement(version, 'last_updated')
        last_updated.text = ctime()

        devs = SubElement(root, 'devices')

        self._walk(self.root_device, devs)

        tree = ElementTree(root)
        tree.write(filename)


if __name__ == '__main__':
    from wurfl import devices
    Serialize(devices).to_xml('my.xml')

