#!/usr/bin/env python
# -*- coding: utf-8 -*-

"Classes mapping to SQL tables"

from docutils.examples import html_body
from django.db import models
from django.contrib.auth.models import User, Group
from django.core.exceptions import ValidationError
from django.utils.html import mark_safe
from django.utils.translation import ugettext_lazy as _

#------------------------------------------------------------------------------
# Utility function for classes using reST (reStructured Text)
def rest_to_html(param):
    "Convert a reST string to html and clean the result"

    start = u'<div class="document">\n<p>'
    end = u"</p>\n</div>\n"

    try:
        rest = html_body(param)
        if rest.startswith(start) and rest.endswith(end):
            rest = rest[len(start):-len(end)] # discard unneeded tags
        rest = mark_safe(rest)
    except StandardError as err:
        print "rest_to_html", err
        rest = str(param)
    return rest

#------------------------------------------------------------------------------
class UserProfile(models.Model):
    "Includes information about user"


    usr = models.ForeignKey(User, to_field='username', related_name='+',
                           verbose_name=_('user info')) # pylint: disable=E1102
    address = models.CharField(_('address'), # pylint: disable=E1102
                                max_length=200)
    phone_number = models.CharField(_('phone number'), # pylint: disable=E1102
                                    max_length=15, blank=True, default='')
    comments = models.CharField(_('comments'), # pylint: disable=E1102
                                    max_length=200, blank=True, default='')

    def __unicode__(self):
        return self.usr

#------------------------------------------------------------------------------
class Classes(models.Model):
    "List of data classes"


    classname = models.TextField(unique=True)

    def __unicode__(self):
        return u'%s' % self.classname

#------------------------------------------------------------------------------
class Base(models.Model):
    "Base class for all (non-relation) classes"


    created_on = models.DateTimeField(auto_now_add=True)
    created_by = models.ForeignKey(User, to_field='username', related_name='+',
                                    editable=False, verbose_name='creator')
    deleted_on = models.DateTimeField(null=True, editable=False)
    deleted_by = models.ForeignKey(User, to_field='username', related_name='+',
                                    null=True, editable=False, default=None)
    classname = models.ForeignKey(Classes, to_field='classname',
                                    related_name='+', editable=False)

    def __unicode__(self):

        res = u"%s" % (self.classname)
        if self.deleted_by:
            res += u" DELETED"
        return res

    def show_details(self):
        'Return a list of the fields for detailed view'

        info_dict = [
          ('Class', self.classname.classname), # pylint: disable=E1101
          ('Created by', self.created_by), # pylint: disable=E1101
          ('Created on',
           self.created_on.strftime("%d.%m.%Y %H:%M"))] # pylint: disable=E1101
        if self.deleted_by and self.deleted_on:
            info_dict.extend([('Deleted by', self.deleted_by),
                              ('Deleted on', self.deleted_on)])
        return info_dict

#------------------------------------------------------------------------------
class DeskTop(models.Model):
    "List of data on the users desktop"


    base = models.ForeignKey(Base, related_name='+')
    user = models.ForeignKey(User, related_name='+')

    class Meta(): # pylint: disable=C0111,C1001,W0232,R0903

        unique_together = (("base", "user"),)

    def __unicode__(self):

        return u'%s' % self.base

#------------------------------------------------------------------------------
class GroupDeskTop(models.Model):
    "List of user's group  on the users desktop"


    group = models.ForeignKey(Group, related_name='+')
    user = models.ForeignKey(User, related_name='+')

    class Meta(): # pylint: disable=C0111,C1001,W0232,R0903

        unique_together = (("group", "user"),)

    def __unicode__(self):

        return u'%s' % self.group

#------------------------------------------------------------------------------
class DataGroup(Base):
    "Links used to link Group and Data"


    group = models.ForeignKey(Group, related_name='+')
    data = models.ForeignKey(Base, related_name='+')

    class Meta(): # pylint: disable=C0111,C1001,W0232,R0903

        unique_together = (("group", "data"),)

    def __unicode__(self):

        return u'DataGroup: %s in %s group' % (self.data, self.group.name)

    def show_details(self):

        info_dict = [('Group', self.group), ('Data', self.data)]
        info_dict.extend(Base.show_details(self))
        return info_dict

#------------------------------------------------------------------------------
class UserGroupPerm(Base):
    "Permissions of a user in a group"


    user = models.ForeignKey(User, related_name='+')
    group = models.ForeignKey(Group, related_name='+')
    read = models.BooleanField(default=True)
    write = models.BooleanField(default=False)
    master = models.BooleanField(default=False)

    class Meta(): # pylint: disable=C0111,C1001,W0232,R0903

        unique_together = (("user", "group"),)

    def clean(self):

        if not self.read and not self.write and not self.master:
            raise ValidationError('PERMIS_DELETED')

    def __unicode__(self):

        res = []
        if self.read:
            res.append('can read')
        if self.write:
            res.append('can write')
        if self.master:
            res.append('group master')
        return "%s (%s): " % (self.user.username, # pylint: disable=E1101
                              self.group.name) + ', '.join(res)

    def show_details(self):

        info_dict = [('UserID', self.user), ('GroupID', self.group),
                    ('Read', self.read), ('Write', self.write)]
        info_dict.extend(Base.show_details(self))
        return info_dict

#------------------------------------------------------------------------------
class LinkType(Base):
    "Links used to link object of class name 1 to object of class name 2"


    link_type = models.TextField()
    classname1 = models.ForeignKey(Classes, to_field='classname',
                                  related_name='+', null=True)
    classname2 = models.ForeignKey(Classes, to_field='classname',
                                  related_name='+', null=True)
    commutative = models.BooleanField(default=False)
    transitive = models.BooleanField(default=False)
    nonidempotent = models.BooleanField(default=False)
    composition = models.BooleanField(default=False)
    remark = models.BooleanField(default=False)

    class Meta(): # pylint: disable=C0111,C1001,W0232,R0903

        unique_together = ('link_type', 'classname1', 'classname2')

    def __unicode__(self):

        class1 = self.classname1 \
                        if self.classname1 else None # pylint: disable=E1101
        class2 = self.classname2 \
                        if self.classname2 else None # pylint: disable=E1101
        return u'%s (%s - %s): %s' % (self.link_type, class1, class2,
                                      Base.__unicode__(self))

    def show_details(self):

        class1 = self.classname1 if self.classname1 else None
        class2 = self.classname2 if self.classname2 else None

        info_dict = [('Link Type', self.link_type),
                    ('Links class', "%s to class: %s" % (class1, class2)),
                    ('Commutative', self.commutative),
                    ('Transitive', self.transitive),
                    ('Nonidempotent', self.nonidempotent),
                    ('Composition', self.composition),
                    ('Remark', self.remark)]
        info_dict.extend(Base.show_details(self))

        return info_dict

#------------------------------------------------------------------------------
class ClassDeskTop(models.Model):
    "List of user's class  on the users desktop"


    classname = models.ForeignKey(Classes, related_name='+')
    user = models.ForeignKey(User, related_name='+')

    class Meta(): # pylint: disable=C0111,C1001,W0232,R0903

        unique_together = (("classname", "user"),)

    def __unicode__(self):

        return u'%s' % self.classname
