# coding: utf-8

import re
import Levenshtein
from itertools import cycle

samogloski = u'eyuioaęóą'
spolgloski = u'qwrtipsdfghjklzxcvbnmśłżźćń'
gloski_spolgloski = u'w r t p s d f g h j k l z c b n m ż ź sz ś dż dź'.split()
litery = samogloski + spolgloski

def gloskuj(slowo):
    slowo = slowo.lower()
    slowo = re.sub(ur'é', u'e', slowo)
    slowo = re.sub(u'[^{0}]'.format(litery), r'', slowo)
    slowo = re.sub(u'([{0}])'.format(litery), r' \1 ', slowo)
    slowo = re.sub(ur'  ', u' ', slowo)
    slowo = re.sub(ur'^ ', u'', slowo)
    slowo = re.sub(ur' $', u'', slowo)
    
    slowo = re.sub(ur'd z i', u'dzi', slowo)
    slowo = re.sub(ur'c h', u'ch', slowo)
    slowo = re.sub(ur'c z', u'cz', slowo)
    slowo = re.sub(ur'd z', u'dz', slowo)
    slowo = re.sub(ur'd ź', u'dź', slowo)
    slowo = re.sub(ur'd ż', u'dż', slowo)
    slowo = re.sub(ur'r z', u'rz', slowo)
    slowo = re.sub(ur's z', u'sz', slowo)
    
    slowo = re.sub(ur'dzi ([{}])'.format(samogloski), ur'dź \1', slowo)
    slowo = re.sub(ur'dzi ([{}])'.format(spolgloski), ur'dź i \1', slowo)
    slowo = re.sub(ur'dzi$', ur'dź i', slowo)
    
    slowo = re.sub(ur'c i ([{}])'.format(samogloski), ur'ć \1', slowo)
    slowo = re.sub(ur'c i ([{}])'.format(spolgloski), ur'ć i \1', slowo)
    slowo = re.sub(ur'c i$', ur'ć i', slowo)

    slowo = re.sub(ur's i ([{}])'.format(samogloski), ur'ś \1', slowo)
    slowo = re.sub(ur's i ([{}])'.format(spolgloski), ur'ś i \1', slowo)
    slowo = re.sub(ur's i$', ur'ś i', slowo)

    slowo = re.sub(ur'z i ([{}])'.format(samogloski), ur'ź \1', slowo)
    slowo = re.sub(ur'z i ([{}])'.format(spolgloski), ur'ź i \1', slowo)
    slowo = re.sub(ur'z i$', ur'ź i', slowo)

    slowo = re.sub(ur'n i ([{}])'.format(samogloski), ur'ń \1', slowo)
    slowo = re.sub(ur'n i ([{}])'.format(spolgloski), ur'ń i \1', slowo)
    slowo = re.sub(ur'n i$', ur'ń i', slowo)

    slowo = re.sub(ur'([{}]) i ([{}])'.format(spolgloski, samogloski), ur'\1 j \2', slowo)

    slowo = re.sub(ur'rz', ur'ż', slowo)
    slowo = re.sub(ur'ch', ur'h', slowo)
    slowo = re.sub(ur'ó', ur'u', slowo)

    slowo = re.sub(ur'ą$', ur'o ł', slowo)
    slowo = re.sub(ur'ą ł$', ur'o ł', slowo)
    slowo = re.sub(ur'ę$', ur'e', slowo)

    slowo = re.sub(ur'ę (w|f|s|z|sz|z|ż|h|ź)', ur'e ł \1', slowo)
    slowo = re.sub(ur'ą (w|f|s|z|sz|z|ż|h|ź)', ur'o ł \1', slowo)

    slowo = re.sub(ur'ę (p|b|m)', ur'e m \1', slowo)
    slowo = re.sub(ur'ą (p|b|m)', ur'o m \1', slowo)

    slowo = re.sub(ur'ę (t|d|c|cz|ż|ć)', ur'e n \1', slowo)
    slowo = re.sub(ur'ą (t|d|c|cz|ż|ć)', ur'o n \1', slowo)

    slowo = re.sub(ur'ę ([^kg])', ur'e \1', slowo)
    slowo = re.sub(ur'ą ([^kg])', ur'o \1', slowo)

    slowo = re.sub(ur'([tpsfhk]) ż', ur'\1 sz', slowo)
    slowo = re.sub(ur'([tpsfhk]) w', ur'\1 f', slowo)

    slowo = re.sub(ur'([{}]) ł$'.format(spolgloski), ur'\1', slowo)
    
    gloski = list(reversed(slowo.split()))
    for i in xrange(len(gloski)):
        gloska = gloski[i]
        if not gloska in gloski_spolgloski:
            break
        gloska = zmien_spolgloske_w_bezdzwieczna(gloska)
        gloski[i] = gloska
    
    slowo = ' '.join(reversed(gloski))
    return slowo

def gloskuj_tekst_wielolinijkowy(tekst):
    tekst_podzielony = [(linia, linia.split()) for linia in tekst.split(u'\n')]
    return [(linia, [gloskuj(slowo).split() for slowo in slowa]) for linia, slowa in tekst_podzielony]

def daj_ostatnie_slowo(tresc):
    tresc = re.sub(r'[^\w ]', ' ', tresc, flags=re.UNICODE).rstrip()
    try:
        ostatnie_slowo = re.findall(ur'\b(\S*)$', tresc)[0]
        ostatnie_slowo = re.sub(ur'[^{0}{1}]'.format(litery, litery.upper()), ur'', ostatnie_slowo)
        return ostatnie_slowo
    except IndexError:
        return u''

def daj_koncowke(slowo):
    gloski = gloskuj(slowo).split(u' ')
    pozycja_ostatniej_samogloski = None
    pozycja_przedostatniej_samogloski = None
    i = len(gloski) - 1
    while i >= 0:
        gloska = gloski[i]
        if gloska in samogloski:
            if pozycja_ostatniej_samogloski is None:
                pozycja_ostatniej_samogloski = i
            else:
                pozycja_przedostatniej_samogloski = i
                break
        i -= 1
    pozycja_ostatniej_akcentowanej_samogloski = pozycja_przedostatniej_samogloski if not pozycja_przedostatniej_samogloski is None else pozycja_ostatniej_samogloski if not pozycja_ostatniej_samogloski is None else None
    if pozycja_ostatniej_akcentowanej_samogloski is None:
        return u''
    return u''.join(gloski[pozycja_ostatniej_akcentowanej_samogloski:])

def zbierz_bliskie_wiersze_w_pary(wiersze):
    pary = []
    for a in xrange(len(wiersze) - 1):
        for b in xrange(a + 1, min(a + 10, len(wiersze))):
            pary.append((a, b))
    return pary

def posortuj_pary_wierszy_wedlug_zrymowania(wiersze, pary):
    pary_ze_zrymowaniem = [(a, b, Levenshtein.ratio(daj_koncowke(daj_ostatnie_slowo(wiersze[a])), daj_koncowke(daj_ostatnie_slowo(wiersze[b])))) for a, b in pary if wiersze[a] != '' and wiersze[b] != '']
    pary_ze_zrymowaniem.sort(key=lambda a: -a[2])
    return pary_ze_zrymowaniem 

def czy_sie_rymuja(slowo1, slowo2, prog):
    koncowka1 = daj_koncowke(slowo1)
    koncowka2 = daj_koncowke(slowo2)
    return Levenshtein.ratio(koncowka1, koncowka2) >= prog

def oznacz_kolorami_grupy_zrymowane(wiersze, prog):
    wynik = []
    rymy = {}
    wiersze_zrymowane = set()
    for numer_wiersza in xrange(len(wiersze)):
      for numer_drugiego_wiersza in xrange(numer_wiersza + 1, min(numer_wiersza + 4 + 1, len(wiersze))):
        if czy_sie_rymuja(daj_ostatnie_slowo(wiersze[numer_wiersza]), daj_ostatnie_slowo(wiersze[numer_drugiego_wiersza]), prog):
          rymy[numer_wiersza] = numer_drugiego_wiersza
          wiersze_zrymowane.add(numer_wiersza)
          wiersze_zrymowane.add(numer_drugiego_wiersza)
          break
    grupy_zrymowane = set()
    for numer_wiersza in xrange(len(wiersze)):
      if numer_wiersza in rymy:
        grupa_zrymowana = set()
        while True:
          grupa_zrymowana.add(numer_wiersza)
          if numer_wiersza in rymy:
            stary_numer_wiersza = numer_wiersza
            numer_wiersza = rymy[numer_wiersza]
            del rymy[stary_numer_wiersza]
          else:
            break
        grupy_zrymowane.add(frozenset(grupa_zrymowana))

    kolory = cycle(('ffdefb', 'deffe2', 'deebff', 'dee1ff', 'ffdef1', 'fffcde', 'deffec'))
    kolory_wierszy = {}
    grupy_zrymowane_posortowane = list(grupy_zrymowane)
    grupy_zrymowane_posortowane.sort(key = lambda grupa: min(grupa))
    for grupa_zrymowana in grupy_zrymowane_posortowane:
      kolor = kolory.next()
      for numer_wiersza in grupa_zrymowana:
        kolory_wierszy[numer_wiersza] = kolor

    for numer_wiersza in xrange(len(wiersze)):
      try:
        kolor = kolory_wierszy[numer_wiersza]
      except KeyError:
        kolor = ''
      wynik.append({
        'linia': wiersze[numer_wiersza],
        'kolor': kolor
      })
    return wynik

def zmien_spolgloske_w_bezdzwieczna(gloska):
    gloska = re.sub(ur'^z', u's', gloska)
    gloska = re.sub(ur'^dż', u'cz', gloska)
    gloska = re.sub(ur'^dź', u'ć', gloska)
    gloska = re.sub(ur'^w', u'f', gloska)
    gloska = re.sub(ur'^d', u't', gloska)
    gloska = re.sub(ur'^g', u'k', gloska)
    gloska = re.sub(ur'^b', u'p', gloska)
    gloska = re.sub(ur'^ż', u'sz', gloska)
    gloska = re.sub(ur'^ź', u'ś', gloska)
    return gloska
