from django.contrib.contenttypes.fields import GenericRelation
from django.db import models

from meanings.models import LexicalUnit, Synset

from . import choices


class Frame(models.Model):
    lexical_units = models.ManyToManyField(LexicalUnit, related_name='frames')
    opinion = models.ForeignKey('FrameOpinion', on_delete=models.PROTECT)
    arguments_count = models.PositiveIntegerField(null=False, default=0) #na potrzeby filtrowania
    status = models.TextField(
        max_length=10,
        choices=choices.FrameStatus.choices,
        default=choices.FrameStatus.NEW,
    )
    assignments = GenericRelation("users.Assignment", content_type_field="subject_ct", object_id_field="subject_id")

    def sorted_arguments(self):  # TODO: zaimplementowac wlasciwe sortowanie
        return Argument.objects.filter(frame=self)

    def __str__(self):
        return '%s: %s' % (self.opinion, ' + '.join([str(arg) for arg in self.sorted_arguments()]))


class FrameOpinion(models.Model):
    key = models.CharField(max_length=16, unique=True)
    # name = TODO wymaga lokalizacji
    priority = models.PositiveIntegerField()

    class Meta:
        ordering = ['priority']

    def __str__(self):
        return self.key


class Argument(models.Model):
    #rola
    role = models.ForeignKey('ArgumentRole', on_delete=models.PROTECT)

    #3 typy preferencji
    predefined = models.ManyToManyField('PredefinedSelectionalPreference')
    synsets = models.ManyToManyField(Synset)
    relations = models.ManyToManyField('RelationalSelectionalPreference')

    #odwoĊ‚anie do ramy
    frame = models.ForeignKey(Frame, related_name='arguments', on_delete=models.PROTECT)

    #do wyszukiwania
    preferences_count = models.PositiveIntegerField(null=False, default=0)

    def __str__(self):
        return str(self.role)


class ArgumentRole(models.Model):
    role = models.ForeignKey('SemanticRole', on_delete=models.PROTECT)
    attribute = models.ForeignKey('RoleAttribute', null=True, on_delete=models.PROTECT)

    def __str__(self):
        if self.attribute is None:
            return str(self.role)
        else:
            return '{}, {}'.format(str(self.role), str(self.attribute))


class SemanticRole(models.Model):
    role = models.CharField(max_length=20)
    color = models.CharField(max_length=11, null=True)
    priority = models.PositiveIntegerField()

    class Meta:
        ordering = ['priority']

    def __str__(self):
        return self.role


class RoleAttribute(models.Model):
    attribute = models.CharField(max_length=20)
    gradient = models.CharField(max_length=10, null=True)
    priority = models.PositiveIntegerField()

    class Meta:
        ordering = ['priority']

    def __str__(self):
        return self.attribute


class RoleType(models.Model):
    type = models.CharField(max_length=20)

    def __str__(self):
        return self.type


class PredefinedSelectionalPreference(models.Model):
    name = models.CharField(max_length=20, unique=True)
    members = models.ForeignKey('SelectivePreference', null=True, on_delete=models.PROTECT)
    # name = TODO: wymaga lokalizacji

    def __str__(self):
        return self.name

class RelationalSelectionalPreference(models.Model):
    relation = models.ForeignKey('SelectionalPreferenceRelation', on_delete=models.PROTECT)
    to = models.ForeignKey('Argument', on_delete=models.PROTECT)

    def __str__(self):
        return '%s -> %s' % (self.relation, self.to)

class SelectivePreferenceRelations(models.Model):
    plwn_id = models.IntegerField(null=True)
    name = models.CharField(max_length=80)
    sym_name = models.CharField(max_length=40)

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

class SynsetRelationalSelectivePreference(models.Model):
    relation = models.ForeignKey(SelectivePreferenceRelations, on_delete=models.PROTECT)
    to = models.ForeignKey(Synset, on_delete=models.PROTECT)

class SelectivePreference(models.Model):
    generals = models.ManyToManyField(PredefinedSelectionalPreference)
    synsets = models.ManyToManyField(Synset)
    relations = models.ManyToManyField(RelationalSelectionalPreference)
    synset_relations = models.ManyToManyField(SynsetRelationalSelectivePreference)


class SelectionalPreferenceRelation(models.Model):
    key = models.CharField(max_length=40, unique=True)
    # name = TODO: wymaga lokalizacji
    plwn_id = models.IntegerField(null=True)
    
    class Meta:
        ordering = ['key']

    def __str__(self):
        return self.key