# Copyright (C) 2003 by Intevation GmbH
# Authors:
# Jan-Oliver Wagner <jan@intevation.de>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with Thuban for details.

"""
Classes for generic ArcView ODB Objects
as in '.apr', '.avl' and other files.
"""

__version__ = "$Revision: 1.2 $"

from types import StringType

from Thuban import _

class ODBBaseObject:

    """Base class for ODB objects."""

    _obj_refs = [] # override this list with the object names
                   # as strings that are referenced.
    _values = []   # override this list with the keywords
                   # for known values of the class.

    def __init__(self, parent_odb, type, number):
        self._parent_odb = parent_odb
        self.type = type
        self.number = number

    def __setattr__(self, attr, value):
        """If an attribute is set that already exists,
        a list is created to contain both. Any further
        attribute with the same name is appended to the list.
        """
        if hasattr(self, attr):
            v = getattr(self, attr)
            if isinstance(v, list):
                v.append(value)
            else:
                self.__dict__[attr] = [v, value]
        else:
            self.__dict__[attr] = value

    def __repr__(self):
        """The string represenation of an object is the syntax
        as used in the ODB file.
        """
        s = '(' + self.type + '.' + str(self.number) + '\n'
        for k in self.__dict__.keys():
            if k in [ '_parent_odb', 'type', 'number']: continue
            v = self.__dict__[k]
            if isinstance(v, list):
                for val in v:
                    s += "\t%s:\t%s\n" % (k, val)
            else:
                s += "\t%s:\t%s\n" % (k, v)
        s += ')\n'
        return s

    def Get(self, attr):
        """If an attribute is a pointer (or a list of pointers)
        to another object (other objects), references are resolved
        to point to the corresponding objects.

        attr -- string with the name of the attribute
        """
        if not hasattr(self, attr):
            print "Object %s.%s has no attribute %s!" % ( self.type,
                    self.number, attr)
            return None

        if attr in self._obj_refs:
            if isinstance(self.__dict__[attr], list): 
                lst = []
                for obj_id in self.__dict__[attr]:
                    obj_id = int(obj_id)
                    if not self._parent_odb.GetObjects().has_key(obj_id):
                        print "Object #%d missing!" % obj_id
                    else:
                        lst.append(self._parent_odb.GetObjects()[obj_id])
                return lst
            else:
                obj_id = int(self.__dict__[attr])
                if not self._parent_odb.GetObjects().has_key(obj_id):
                    print "Object #%d missing!" % s
                    return None
                return self._parent_odb.GetObjects()[obj_id]

        return self.__dict__[attr]

    def TreeInfo(self):
        """Return the information in a tree-like structure."""
        items = []

        # known values
        for o in self._values:
            if hasattr(self, o):
                items.append('%s: %s' % (o, self.Get(o)))

        # the objects
        for o in self._obj_refs:
            if not hasattr(self, o): continue
            if not isinstance(self.Get(o), list):
                items.append(self.Get(o).TreeInfo())
                # add the variable name of the object:
                items[-1][0] = '%s: %s' % (o, items[-1][0])
                continue
            for obj in self.Get(o):
                items.append(obj.TreeInfo())
                # add the variable name of the object:
                items[-1][0] = '%s: %s' % (o, items[-1][0])

        # unknown values
        for k in self.__dict__.keys():
            if k in [ '_parent_odb', 'type', 'number']: continue
            if k in self._obj_refs: continue
            if k in self._values: continue
            v = self.__dict__[k]
            if isinstance(v, list):
                items.append(_("Unknown Object list named: '%s'") % k)
            else:
                if isinstance(v, StringType):
                    items.append(_("Unknown Value named: '%s' with value '%s'")\
                        % ( k, v ))
                else:
                    items.append(_('Unknown Object named: %s') % k)

        return [self.type, items]
