# Path: models/user.py
# class User(Document, UserMixin):
#     username = StringField(max_length=200)
#     password = StringField(max_length=200, default='')
#     name = StringField(max_length=100)
#     email = EmailField()
#     active = BooleanField(default=True)
#     admin = BooleanField(default=False)
#     last_login = DateTimeField(default=datetime.datetime.now)
#     skipped = IntField(default=0)
#     processed = IntField(default=0)
#     tags = ListField(StringField(), default=[])
#     tags_count = IntField(default=0, db_field='tagsCount')
# 
#     def is_active(self):
#         return self.active
# 
#     def is_admin(self):
#         return self.admin or False
# 
#     def __unicode__(self):
#         return self.username
# 
# Path: models/shreds.py
# class Cluster(Document):
#     """Cluster of one or more shreds.
# 
#     Shred membership described with a ClusterMember embedded document, which
#     contains a reference to the shred and its relative position and angle in a
#     cluster.
# 
#     Cluster also contains user-generated tagging results (tags field).
#     """
#     id = StringField(max_length=200, default='', primary_key=True)
# 
#     users_count = IntField(default=0, db_field='usersCount')
#     users_skipped = ListField(ReferenceField(User), db_field='usersSkipped')
#     users_processed = ListField(ReferenceField(User),
#                                 db_field='usersProcessed')
# 
#     batch = StringField(required=True)
#     tags = ListField(EmbeddedDocumentField(ShredTags))
# 
#     members = ListField(EmbeddedDocumentField(ClusterMember))
#     parents = ListField(ReferenceField('Cluster'))
# 
#     def __unicode__(self):
#         return self.id
# 
#     @property
#     def features(self):
#         # TODO: persist features on creation.
#         return self.members[0].shred.features
# 
#     def get_user_tags(self, user):
#         for shred_tags in self.tags:
#             # in some rare cases user reference from shred_tags has no pk field
#             if shred_tags.user.id == user.pk:
#                 return shred_tags
#         return None
# 
#     @property
#     def auto_tags(self):
#         return sum((member.shred.auto_tags for member in self.members), [])
# 
#     @property
#     def render_auto_tags(self):
#         auto_tags = self.auto_tags
#         res = []
#         for t in auto_tags:
#             if not t.startswith('color:'):
#                 res.append(jinja2.escape(t))
#                 continue
# 
#             color_tmpl = (
#                 "<span style='height:15px;width:40px;background-color:#%s;display:inline-block'>" +
#                 "&nbsp;</span>")
# 
#             res.append(color_tmpl % t[len('color:'):])
# 
#         return jinja2.Markup(', '.join(res))
# 
#     @property
#     def all_tags(self):
#         return sorted(set(t for st in self.tags for t in st.tags))
# 
#     def get_repeated_tags(self, repeats=2):
#         tags_counts = Counter(self.all_tags)
#         return (set(
#             [tag for tag, count in tags_counts.items() if count >= repeats]) |
#             set(self.auto_tags))
# 
#     @staticmethod
#     def next_for_user(user, users_per_shred):
#         # TODO: add randomisation.
#         cluster = Cluster\
#             .objects(users_processed__ne=user.id, users_skipped__ne=user.id,
#                      users_count__lte=users_per_shred)\
#             .order_by("users_count").first()
# 
#         if cluster:
#             return cluster
# 
#         cluster = Cluster\
#             .objects(users_skipped=user.to_dbref(), users_count__lte=users_per_shred)\
#             .order_by("users_count").first()
# 
#         if cluster:
#             Cluster.objects(id=cluster.id).update_one(
#                 pull__users_skipped=user.to_dbref())
# 
#         return cluster
# 
#     @classmethod
#     def get_some(cls, batch=None):
#         # TODO: Pick appropriate cluster.
#         qs = cls.objects
#         if batch is not None:
#           qs = qs.filter(batch=batch)
#         num = random.randint(0, qs.count()-1)
#         some_clusters = qs[num:num+1]
#         if some_clusters:
#             return some_clusters[0]
#         return None
# 
#     @property
#     def num_members(self):
#         return len(self.members)
# 
#     @property
#     def image_html(self):
#         if self.num_members != 1:
#             return ''
# 
#         return jinja2.Markup('<img src="%s" />' %
#                              self.members[0].shred.piece_fname)


import datetime
import random
from mongoengine import (
    FloatField, IntField, DateTimeField, ListField, ReferenceField,
    StringField, CASCADE)
from flask_mongoengine import Document
from .user import User
from .shreds import Cluster




class TaggingSpeed(Document):
    """
    Metric to measure time required to process single shred and see
    how that correlates with UI changes.
    """

    tagged_at = DateTimeField(default=datetime.datetime.utcnow)
    msec = FloatField()
    tags_count = IntField()
    user = ReferenceField(User, reverse_delete_rule=CASCADE)
    cluster = ReferenceField(Cluster, reverse_delete_rule=CASCADE)


class ShredsDistances(Document):
    """
    Distance types are:
    - jaccard: Jaccard distance. http://en.wikipedia.org/wiki/Jaccard_index
    - tf-idf: term frequency-inverse document frequency
            http://en.wikipedia.org/wiki/Tf-idf
    """


# Path: models/user.py
# class User(Document, UserMixin):
#     username = StringField(max_length=200)
#     password = StringField(max_length=200, default='')
#     name = StringField(max_length=100)
#     email = EmailField()
#     active = BooleanField(default=True)
#     admin = BooleanField(default=False)
#     last_login = DateTimeField(default=datetime.datetime.now)
#     skipped = IntField(default=0)
#     processed = IntField(default=0)
#     tags = ListField(StringField(), default=[])
#     tags_count = IntField(default=0, db_field='tagsCount')
# 
#     def is_active(self):
#         return self.active
# 
#     def is_admin(self):
#         return self.admin or False
# 
#     def __unicode__(self):
#         return self.username
# 
# Path: models/shreds.py
# class Cluster(Document):
#     """Cluster of one or more shreds.
# 
#     Shred membership described with a ClusterMember embedded document, which
#     contains a reference to the shred and its relative position and angle in a
#     cluster.
# 
#     Cluster also contains user-generated tagging results (tags field).
#     """
#     id = StringField(max_length=200, default='', primary_key=True)
# 
#     users_count = IntField(default=0, db_field='usersCount')
#     users_skipped = ListField(ReferenceField(User), db_field='usersSkipped')
#     users_processed = ListField(ReferenceField(User),
#                                 db_field='usersProcessed')
# 
#     batch = StringField(required=True)
#     tags = ListField(EmbeddedDocumentField(ShredTags))
# 
#     members = ListField(EmbeddedDocumentField(ClusterMember))
#     parents = ListField(ReferenceField('Cluster'))
# 
#     def __unicode__(self):
#         return self.id
# 
#     @property
#     def features(self):
#         # TODO: persist features on creation.
#         return self.members[0].shred.features
# 
#     def get_user_tags(self, user):
#         for shred_tags in self.tags:
#             # in some rare cases user reference from shred_tags has no pk field
#             if shred_tags.user.id == user.pk:
#                 return shred_tags
#         return None
# 
#     @property
#     def auto_tags(self):
#         return sum((member.shred.auto_tags for member in self.members), [])
# 
#     @property
#     def render_auto_tags(self):
#         auto_tags = self.auto_tags
#         res = []
#         for t in auto_tags:
#             if not t.startswith('color:'):
#                 res.append(jinja2.escape(t))
#                 continue
# 
#             color_tmpl = (
#                 "<span style='height:15px;width:40px;background-color:#%s;display:inline-block'>" +
#                 "&nbsp;</span>")
# 
#             res.append(color_tmpl % t[len('color:'):])
# 
#         return jinja2.Markup(', '.join(res))
# 
#     @property
#     def all_tags(self):
#         return sorted(set(t for st in self.tags for t in st.tags))
# 
#     def get_repeated_tags(self, repeats=2):
#         tags_counts = Counter(self.all_tags)
#         return (set(
#             [tag for tag, count in tags_counts.items() if count >= repeats]) |
#             set(self.auto_tags))
# 
#     @staticmethod
#     def next_for_user(user, users_per_shred):
#         # TODO: add randomisation.
#         cluster = Cluster\
#             .objects(users_processed__ne=user.id, users_skipped__ne=user.id,
#                      users_count__lte=users_per_shred)\
#             .order_by("users_count").first()
# 
#         if cluster:
#             return cluster
# 
#         cluster = Cluster\
#             .objects(users_skipped=user.to_dbref(), users_count__lte=users_per_shred)\
#             .order_by("users_count").first()
# 
#         if cluster:
#             Cluster.objects(id=cluster.id).update_one(
#                 pull__users_skipped=user.to_dbref())
# 
#         return cluster
# 
#     @classmethod
#     def get_some(cls, batch=None):
#         # TODO: Pick appropriate cluster.
#         qs = cls.objects
#         if batch is not None:
#           qs = qs.filter(batch=batch)
#         num = random.randint(0, qs.count()-1)
#         some_clusters = qs[num:num+1]
#         if some_clusters:
#             return some_clusters[0]
#         return None
# 
#     @property
#     def num_members(self):
#         return len(self.members)
# 
#     @property
#     def image_html(self):
#         if self.num_members != 1:
#             return ''
# 
#         return jinja2.Markup('<img src="%s" />' %
#                              self.members[0].shred.piece_fname)


# Path: models/metrics.py
import datetime
import random
from mongoengine import (
    FloatField, IntField, DateTimeField, ListField, ReferenceField,
    StringField, CASCADE)
from flask_mongoengine import Document
from .user import User
from .shreds import Cluster





class TaggingSpeed(Document):
    """
    Metric to measure time required to process single shred and see
    how that correlates with UI changes.
    """

    tagged_at = DateTimeField(default=datetime.datetime.utcnow)
    msec = FloatField()
    tags_count = IntField()
    user = ReferenceField(User, reverse_delete_rule=CASCADE)
    cluster = ReferenceField(Cluster, reverse_delete_rule=CASCADE)


class ShredsDistances(Document):
    """
    Distance types are:
    - jaccard: Jaccard distance. http://en.wikipedia.org/wiki/Jaccard_index
    - tf-idf: term frequency-inverse document frequency
            http://en.wikipedia.org/wiki/Tf-idf
    """


    shreds_pair = ListField(ReferenceField(Cluster))