from uuid import uuid4
from unidecode import unidecode

from django.db import models
from django.utils.encoding import smart_unicode
from django.conf import settings
from django.template.defaultfilters import slugify
from django.utils.functional import curry
from django.utils.translation import ugettext_lazy as _, get_language
from anora.templatetags.anora import CONSONANT_SOUND, VOWEL_SOUND
from i18n.utils import normalize_language_code

from nouns.utils import get_synsets, get_lemmas, from_lemma


class Noun(models.Model):
    text = models.CharField(max_length=255, db_index=True)
    slug = models.SlugField(max_length=255, blank=True)
    language = models.CharField(max_length=25)
    is_active = models.BooleanField(default=True)

    class Meta:
        unique_together = (("text", "language"),)

    def __unicode__(self):
        return smart_unicode(self.text).title()

    def save(self, *args, **kwargs):
        if not self.slug:
            slug = slugify(unidecode(self.text))
            duplications = Noun.objects.filter(slug=slug,
                                               language=self.language)
            if duplications.exists():
                self.slug = "%s-%s" % (slug, uuid4().hex)
            else:
                self.slug = slug
        return super(Noun, self).save(*args, **kwargs)

    @classmethod
    def from_synset(cls, synset):
        lemmas = synset.lemma_names()
        text = lemmas[0]
        keywords = lemmas[1:]
        noun, created = cls.objects.get_or_create(
            text=from_lemma(text),
            defaults={
                'is_active': False,
                'language': normalize_language_code(get_language())
            })
        for keyword in keywords:
            noun.add_keyword(from_lemma(keyword))
        return noun

    def update_with_wordnet(self, update_antonyms=True):
        synsets = get_synsets(self.text)

        if not synsets:
            return

        for synset in synsets:
            path = synset.hypernym_paths()[0]
            parents = path[:-1]
            parent = self
            for hypernym in reversed(parents):
                noun = Noun.from_synset(hypernym)
                parent.add_hypernym(noun)
                parent = noun

            for holonym in synset.part_holonyms():
                noun = Noun.from_synset(holonym)
                self.add_holonym(noun)

            for holonym in synset.member_holonyms():
                noun = Noun.from_synset(holonym)
                self.add_holonym(noun)

        for lemma in get_lemmas(self.text):
            if lemma != self.text:
                self.add_keyword(lemma)

        if not update_antonyms:
            return

        for synset in synsets:
            for lemma in synset.lemmas():
                for antonym in lemma.antonyms():
                    noun = Noun.from_synset(antonym.synset())
                    self.add_antonym(noun)
                    noun.update_with_wordnet(update_antonyms=False)

    def add_keyword(self, text):
        keyword, created = self.keywords.get_or_create(text=text)
        return keyword

    def active_keywords(self):
        return self.keywords.filter(is_active=True)

    def active_contentions(self):
        language = normalize_language_code(get_language())
        return self.contentions.filter(
            is_published=True,