class BoundRelatedObject(object):
    def __init__(self, related_object, field_mapping, original):
        self.relation = related_object
        self.field_mappings = field_mapping[related_object.name]

    def template_name(self):
        raise NotImplementedError

    def __repr__(self):
        return repr(self.__dict__)

class RelatedObject(object):
    def __init__(self, parent_model, model, field):
        self.parent_model = parent_model
        self.model = model
        self.opts = model._meta
        self.field = field
        self.edit_inline = field.rel.edit_inline
        self.name = '%s:%s' % (self.opts.app_label, self.opts.module_name)
        self.var_name = self.opts.object_name.lower()

    def flatten_data(self, follow, obj=None):
        new_data = {}
        rel_instances = self.get_list(obj)
        for i, rel_instance in enumerate(rel_instances):
            instance_data = {}
            for f in self.opts.fields + self.opts.many_to_many:
                # TODO: Fix for recursive manipulators.
                fol = follow.get(f.name, None)
                if fol:
                    field_data = f.flatten_data(fol, rel_instance)
                    for name, value in field_data.items():
                        instance_data['%s.%d.%s' % (self.var_name, i, name)] = value
            new_data.update(instance_data)
        return new_data

    def extract_data(self, data):
        """
        Pull out the data meant for inline objects of this class,
        i.e. anything starting with our module name.
        """
        return data # TODO

    def get_list(self, parent_instance=None):
        "Get the list of this type of object from an instance of the parent class."
        if parent_instance is not None:
            attr = getattr(parent_instance, self.get_accessor_name())
            if self.field.rel.multiple:
                # For many-to-many relationships, return a list of objects
                # corresponding to the xxx_num_in_admin options of the field
                objects = list(attr.all())

                count = len(objects) + self.field.rel.num_extra_on_change
                if self.field.rel.min_num_in_admin:
                    count = max(count, self.field.rel.min_num_in_admin)
                if self.field.rel.max_num_in_admin:
                    count = min(count, self.field.rel.max_num_in_admin)

                change = count - len(objects)
                if change > 0:
                    return objects + [None] * change
                if change < 0:
                    return objects[:change]
                else: # Just right
                    return objects
            else:
                # A one-to-one relationship, so just return the single related
                # object
                return [attr]
        else:
            if self.field.rel.min_num_in_admin:
                return [None] * max(self.field.rel.num_in_admin, self.field.rel.min_num_in_admin)
            else:
                return [None] * self.field.rel.num_in_admin

    def get_db_prep_lookup(self, lookup_type, value):
        # Defer to the actual field definition for db prep
        return self.field.get_db_prep_lookup(lookup_type, value)
        
    def editable_fields(self):
        "Get the fields in this class that should be edited inline."
        return [f for f in self.opts.fields + self.opts.many_to_many if f.editable and f != self.field]

    def get_follow(self, override=None):
        if isinstance(override, bool):
            if override:
                over = {}
            else:
                return None
        else:
            if override:
                over = override.copy()
            elif self.edit_inline:
                over = {}
            else:
                return None

        over[self.field.name] = False
        return self.opts.get_follow(over)

    def get_manipulator_fields(self, opts, manipulator, change, follow):
        if self.field.rel.multiple:
            if change:
                attr = getattr(manipulator.original_object, self.get_accessor_name())
                count = attr.count()
                count += self.field.rel.num_extra_on_change
            else:
                count = self.field.rel.num_in_admin
            if self.field.rel.min_num_in_admin:
                count = max(count, self.field.rel.min_num_in_admin)
            if self.field.rel.max_num_in_admin:
                count = min(count, self.field.rel.max_num_in_admin)
        else:
            count = 1

        fields = []
        for i in range(count):
            for f in self.opts.fields + self.opts.many_to_many:
                if follow.get(f.name, False):
                    prefix = '%s.%d.' % (self.var_name, i)
                    fields.extend(f.get_manipulator_fields(self.opts, manipulator, change,
                                                           name_prefix=prefix, rel=True))
        return fields

    def __repr__(self):
        return "<RelatedObject: %s related to %s>" % (self.name, self.field.name)

    def bind(self, field_mapping, original, bound_related_object_class=BoundRelatedObject):
        return bound_related_object_class(self, field_mapping, original)

    def get_accessor_name(self):
        # This method encapsulates the logic that decides what name to give an
        # accessor descriptor that retrieves related many-to-one or
        # many-to-many objects. It uses the lower-cased object_name + "_set",
        # but this can be overridden with the "related_name" option.
        if self.field.rel.multiple:
            # If this is a symmetrical m2m relation on self, there is no reverse accessor.
            if getattr(self.field.rel, 'symmetrical', False) and self.model == self.parent_model:
                return None
            return self.field.rel.related_name or (self.opts.object_name.lower() + '_set')
        else:
            return self.field.rel.related_name or (self.opts.object_name.lower())
