# -*- coding: utf-8 -*-

from django.db import models

from dictionary.models import Argument, Frame, Position, NKJP_Example, Entry
from wordnet.models import LexicalUnit, Synset
from django.contrib.auth.models import User
from datetime import datetime

################################################
############### Semantic Walenty ###############
################################################

class SemanticRole(models.Model): # lista dostępnych ról semantycznych
        # słowna nazwa roli
    role = models.CharField(max_length=20)
        # kolor przypisany roli
    color = models.CharField(max_length=11, null=True)
        # kierunek gradientu
    gradient = models.CharField(max_length=10, null=True)
    
    def __unicode__(self):
        return '%s' % self.role 
  
class FrameOpinion(models.Model):
    value = models.CharField(max_length=16, unique=True)
    short = models.CharField(max_length=16, blank=True, null=True)
    # okresla kolejnosc prezentowania opinii
    priority = models.PositiveIntegerField(blank=True, null=True)
   
    def __unicode__(self):
      return '%s' % (self.value)
  
class SemanticFrame(models.Model):
        # identyfikator ramki
    id = models.AutoField(primary_key=True)
        # jednostka leksykalna, dla której jest to ramka
    lexical_units = models.ManyToManyField(LexicalUnit, related_name='frames')
    # validation - LexicalUnit must have 'czasownik' in pos field ?
    complements = models.ManyToManyField('Complement')
        # historia zmian
    next = models.ForeignKey('SemanticFrame', null=True)
    removed = models.BooleanField(default=False)
    author = models.ForeignKey(User, null=True)
    opinion = models.ForeignKey(FrameOpinion, null=True)
        # hasło w Walentym
    entry = models.ForeignKey(Entry, null=True, related_name='semantic_frames')
    
    def role_exists(self, role_name):
        if self.complements.filter(roles__role=role_name).exists():
            return True
        return False
    
    def opinion_selected(self):
        if not self.opinion:
            return False
        return True
    
    def connected_schemata(self):
        connected_schemata_ids = []
        for compl in self.complements.all():
            connected_schemata_ids.extend([schema.id for schema in compl.connected_schemata()])
        return Frame.objects.filter(id__in=connected_schemata_ids).distinct()
    
    def __unicode__(self):
        complements_str_tab = [unicode(compl) for compl in self.complements.all()]
        return u'%d --> %s' % (self.id, u'+'.join(complements_str_tab))

class FramePosition(models.Model):
        # schemat
    frame = models.ForeignKey(Frame)
        # pozycja w tym schemacie
    position = models.ForeignKey(Position)
        # argument w tej pozycji
    argument = models.ForeignKey(Argument)
        # numer alternacji
    alternation = models.IntegerField(default=1)
    
    def __unicode__(self):
        return 'schema_%d_pos_%d_arg_%d_alt_%d_' % (self.frame.id, self.position.id,
                                                    self.argument.id, self.alternation)

class LexicalUnitExamples(models.Model):
    example = models.ForeignKey(NKJP_Example)
    lexical_unit = models.ForeignKey(LexicalUnit, null=True)

class GeneralSelectivePreference(models.Model):
    name = models.CharField(max_length=20)
    members = models.ForeignKey('SelectivePreference', null=True)
    
    def __unicode__(self):
        return u'%s' % (self.name)

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

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

class RelationalSelectivePreference(models.Model):
    relation = models.ForeignKey(SelectivePreferenceRelations)
    to = models.ForeignKey('Complement')
    
    def __unicode__(self):
        return u'%s -> %s' % (self.relation, self.to)

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

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

class Complement(models.Model): # pola z ramki
    frame = models.ForeignKey(SemanticFrame)
        # lista ról, które spełnia to pole w ramce
    roles = models.ManyToManyField(SemanticRole)
        # list synsetów definiujących preferencje selektywne
    selective_preference = models.ForeignKey(SelectivePreference, null=True)
    # validation - Synsets in selective preference are not related by hypernymy/hyperonymy
        # realizacje tego argumentu w schematach składniowych
    realizations = models.ManyToManyField(FramePosition)
    
    def has_only_phraseologic_realizations(self):
        for real in self.realizations.all():
            if not real.argument.is_phraseologic():
                return False
        return True
    
    def connected_schemata(self):
        schemata_ids = [real.frame.id for real in self.realizations.all()]
        return Frame.objects.filter(id__in=schemata_ids).distinct()
    
    def __unicode__(self):
        return u'%d:%s' % (self.id, self.roles.all())

################################################
################## Wspomaganie #################
################################################

class FrameRankings(models.Model): # automatyczna ocena ramy
        # dla którego znaczenia schemat jest oceniany
    lexical_unit = models.ForeignKey(LexicalUnit)
        # który schemat jest oceniana
    frame = models.ForeignKey(Frame)
        # ocena
    rank = models.DecimalField(max_digits=5, decimal_places=4)
        # właściwy podschemat oznaczony manualnie
    done = models.BooleanField()

class SemanticRolesDisplay(models.Model):
        # numer wiersza
    row = models.IntegerField()
        # numer kolumny
    column = models.IntegerField()
        # rowspan
    rowspan = models.IntegerField()
        # colspan
    colspan = models.IntegerField()
        # role
    roles = models.ManyToManyField(SemanticRole)
        # napis (np. nagłówek wiersza/kolumny)
    caption = models.CharField(max_length=30, null=True)
