# Path: apps/taxonomy/models.py
# class Tree(models.Model):
#     name = models.CharField(max_length=255)
#     origin_tree = models.ForeignKey('self', related_name='origin', null=True, blank=True)
#     root_node = models.ForeignKey('TaxonNode', related_name='root', null=True, blank=True)  # on trees that hold the whole tree
#     owner_id = models.IntegerField(null=True)
#     created_by = models.IntegerField(null=True)
#     created_at = models.DateTimeField(auto_now_add=True, editable=True, blank=True)
#     updated_by = models.IntegerField(null=True)
#     updated_at = models.DateTimeField(blank=True, default='2000-01-01 00:00:00+03:00')
#     is_public = models.BooleanField(default=False)
#     is_deleted = models.BooleanField(default=False)
# 
#     def create_root_node(self):
#         self.root_node = TaxonNode(epithet=self.name,
#                                    taxon_rank_id=0
#                                    )
#         self.root_node.save()
#         self.root_node.create_edges(parent=None)
#         self.root_node_id = self.root_node.pk
#         self.save()
# 
#     def get_root_children(self):
#         """
#         Return first level children for root node
#         """
#         children_ids = [edge.descendant_id for edge in Edge.objects.filter(ancestor=self.root_node, length=1)]
#         return TaxonNode.objects.filter(pk__in=children_ids)
# 
#     def get_taxon_count(self):
#         return TaxonNode.objects.filter(tree=self).count()
# 
#     def clone_starting_from_taxon_node(self, starting_root_node):
#         TreeCloner.clone(self, starting_root_node)
# 
#     def __unicode__(self):
#         return u"%s" % (self.name)
# 
# class Edge(models.Model):
#     ancestor = models.ForeignKey(TaxonNode, related_name='parent')
#     descendant = models.ForeignKey(TaxonNode, related_name='child')
#     length = models.IntegerField()
# 
# Path: apps/taxonomy/fields/autocomplete_field.py
# class AutocompleteHyperlinkedRelatedField(HyperlinkedRelatedField):
#     """
#     Used in hyperlinked autocomplete fields. Converts the 'id' or
#     full url path of the object into resolvable url.
#     Otherwise acts as a regular HyperlinkedRelatedField
#     """
#     def __init__(self, *args, **kwargs):
#         autocomplete_class = kwargs.pop('autocomplete_class', None)
#         if not autocomplete_class:
#             queryset = kwargs.get('queryset', None)
#             if queryset:
#                 autocomplete_class = '%sAutocomplete' % queryset.model.__name__
#         if autocomplete_class:
#             kwargs["widget"] = autocomplete_light.ChoiceWidget(autocomplete_class)
#         super(AutocompleteHyperlinkedRelatedField, self).__init__(*args, **kwargs)
# 
#     def from_native(self, value):
#         if value.isdigit():
#             # Convert pk to url
#             value = reverse(self.view_name, args=[int(value)])
#             prefix = get_script_prefix()
#             if value.startswith(prefix):
#                 # Remove unnecessary prefixes from url
#                 value = '/' + value[len(prefix):]
# 
#         return super(AutocompleteHyperlinkedRelatedField, self).from_native(value)


import autocomplete_light
from rest_framework import serializers
from apps.taxonomy.models import Tree, Edge
from apps.taxonomy.fields.autocomplete_field import AutocompleteHyperlinkedRelatedField

class TreeSerializer(serializers.HyperlinkedModelSerializer):
    origin_tree = serializers.HyperlinkedRelatedField(many=False, view_name='tree-detail', required=False)

    root_node = AutocompleteHyperlinkedRelatedField(
        widget=autocomplete_light.ChoiceWidget('TaxonNodeAutocomplete'),
        view_name='taxonnode-detail', required=False
    )

    class Meta:
        model = Tree
        fields = [
            'id', 'url', 'name', 'origin_tree', 'root_node'
        ]

    def validate(self, attrs):
        NODE_LIMIT = 5000
        origin_tree_children_count = 0
        root_node_children_count = 0
        root_node = attrs.get("root_node", None)
        origin_tree = attrs.get("origin_tree", None)

        if root_node:
            if origin_tree and (root_node.tree != origin_tree):
                raise serializers.ValidationError("The root_node does not belong to the given tree")
            root_node_children_count = Edge.objects.filter(ancestor=root_node).count()
            if root_node_children_count > NODE_LIMIT:
                raise serializers.ValidationError("Selected root node's taxon count exceeds the allowed limit, please contact site administrator for further details.")

        if origin_tree and origin_tree.root_node:

# Path: apps/taxonomy/models.py
# class Tree(models.Model):
#     name = models.CharField(max_length=255)
#     origin_tree = models.ForeignKey('self', related_name='origin', null=True, blank=True)
#     root_node = models.ForeignKey('TaxonNode', related_name='root', null=True, blank=True)  # on trees that hold the whole tree
#     owner_id = models.IntegerField(null=True)
#     created_by = models.IntegerField(null=True)
#     created_at = models.DateTimeField(auto_now_add=True, editable=True, blank=True)
#     updated_by = models.IntegerField(null=True)
#     updated_at = models.DateTimeField(blank=True, default='2000-01-01 00:00:00+03:00')
#     is_public = models.BooleanField(default=False)
#     is_deleted = models.BooleanField(default=False)
# 
#     def create_root_node(self):
#         self.root_node = TaxonNode(epithet=self.name,
#                                    taxon_rank_id=0
#                                    )
#         self.root_node.save()
#         self.root_node.create_edges(parent=None)
#         self.root_node_id = self.root_node.pk
#         self.save()
# 
#     def get_root_children(self):
#         """
#         Return first level children for root node
#         """
#         children_ids = [edge.descendant_id for edge in Edge.objects.filter(ancestor=self.root_node, length=1)]
#         return TaxonNode.objects.filter(pk__in=children_ids)
# 
#     def get_taxon_count(self):
#         return TaxonNode.objects.filter(tree=self).count()
# 
#     def clone_starting_from_taxon_node(self, starting_root_node):
#         TreeCloner.clone(self, starting_root_node)
# 
#     def __unicode__(self):
#         return u"%s" % (self.name)
# 
# class Edge(models.Model):
#     ancestor = models.ForeignKey(TaxonNode, related_name='parent')
#     descendant = models.ForeignKey(TaxonNode, related_name='child')
#     length = models.IntegerField()
# 
# Path: apps/taxonomy/fields/autocomplete_field.py
# class AutocompleteHyperlinkedRelatedField(HyperlinkedRelatedField):
#     """
#     Used in hyperlinked autocomplete fields. Converts the 'id' or
#     full url path of the object into resolvable url.
#     Otherwise acts as a regular HyperlinkedRelatedField
#     """
#     def __init__(self, *args, **kwargs):
#         autocomplete_class = kwargs.pop('autocomplete_class', None)
#         if not autocomplete_class:
#             queryset = kwargs.get('queryset', None)
#             if queryset:
#                 autocomplete_class = '%sAutocomplete' % queryset.model.__name__
#         if autocomplete_class:
#             kwargs["widget"] = autocomplete_light.ChoiceWidget(autocomplete_class)
#         super(AutocompleteHyperlinkedRelatedField, self).__init__(*args, **kwargs)
# 
#     def from_native(self, value):
#         if value.isdigit():
#             # Convert pk to url
#             value = reverse(self.view_name, args=[int(value)])
#             prefix = get_script_prefix()
#             if value.startswith(prefix):
#                 # Remove unnecessary prefixes from url
#                 value = '/' + value[len(prefix):]
# 
#         return super(AutocompleteHyperlinkedRelatedField, self).from_native(value)


# Path: apps/taxonomy/serializers/tree.py
import autocomplete_light
from rest_framework import serializers
from apps.taxonomy.models import Tree, Edge
from apps.taxonomy.fields.autocomplete_field import AutocompleteHyperlinkedRelatedField


class TreeSerializer(serializers.HyperlinkedModelSerializer):
    origin_tree = serializers.HyperlinkedRelatedField(many=False, view_name='tree-detail', required=False)

    root_node = AutocompleteHyperlinkedRelatedField(
        widget=autocomplete_light.ChoiceWidget('TaxonNodeAutocomplete'),
        view_name='taxonnode-detail', required=False
    )

    class Meta:
        model = Tree
        fields = [
            'id', 'url', 'name', 'origin_tree', 'root_node'
        ]

    def validate(self, attrs):
        NODE_LIMIT = 5000
        origin_tree_children_count = 0
        root_node_children_count = 0
        root_node = attrs.get("root_node", None)
        origin_tree = attrs.get("origin_tree", None)

        if root_node:
            if origin_tree and (root_node.tree != origin_tree):
                raise serializers.ValidationError("The root_node does not belong to the given tree")
            root_node_children_count = Edge.objects.filter(ancestor=root_node).count()
            if root_node_children_count > NODE_LIMIT:
                raise serializers.ValidationError("Selected root node's taxon count exceeds the allowed limit, please contact site administrator for further details.")

        if origin_tree and origin_tree.root_node:

            origin_tree_children_count = Edge.objects.filter(ancestor=origin_tree.root_node).count()