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

'''
Common functions used in Slowal application.
'''

from collections import Counter

from dictionary.models import Position, sortPositions, sortArguments, sortFrameChars

def args_to_pos_lists(arguments):
    positions_objs = []
    for arg in arguments:
        pos_text_rep = '{%s}' % (arg.text_rep)
        pos_objs = Position.objects.filter(text_rep=pos_text_rep) 
        if pos_objs.count() > 0:
            pos_obj = pos_objs.all()[0]
        else:
            pos_obj = Position(text_rep=pos_text_rep)
            pos_obj.save()
            pos_obj.arguments.add(arg)
        positions_objs.append(pos_obj)
    sorted_positions = []  
    sorted_pos_dict = sortPositions(positions_objs)
    for pos_dict in sorted_pos_dict:
        sorted_positions.append(pos_dict['position'])
    sort_pos_str_tab = []
    for sort_pos in sorted_positions:
        sort_pos_str_tab.append(sort_pos.text_rep)  
    return (sort_pos_str_tab, positions_objs)   

def position_data_to_text_rep(categories, arguments):
    sorted_arguments = sortArguments(arguments.all())
    sorted_categories = categories.order_by('priority')
    args_text_reps = [arg.text_rep for arg in sorted_arguments]
    cats_text_reps = [cat.category for cat in sorted_categories]
    position_text_rep = u'%s{%s}' % (','.join(cats_text_reps), ';'.join(args_text_reps))
    return position_text_rep

def frame_data_to_text_rep(characteristics, positions):
    sorted_chars = sortFrameChars(characteristics.all())
    sorted_positions = sortPositions(positions.all())
    chars_text_reps = [char.value.value for char in sorted_chars]
    positions_text_reps = [pos['position'].text_rep for pos in sorted_positions]
    frame_text_rep = u'%s:%s' % (':'.join(chars_text_reps), '+'.join(positions_text_reps)) 
    return frame_text_rep
    

#######################

def subframe_exists(frames, subframe):
    exists = False
    for frame in frames:
        if is_subframe(frame, subframe):
            exists = True
            break
    return exists        

def is_subframe(frame, subframe, ignore_characteristics=True):
    match = False
    wrong_frame = False
    for subframe_pos in subframe.positions.all(): 
        unmatched_poss = list(frame.positions.all())
        smallest_poss = None
        for frame_pos in unmatched_poss:
            frame_args = set(frame_pos.arguments.all())
            subframe_args = set(subframe_pos.arguments.all())
            if len(subframe_args - frame_args) == 0:
                if (not smallest_poss or 
                    smallest_poss.arguments.count() > frame_pos.arguments.count()): 
                    smallest_poss = frame_pos
        if not smallest_poss:
            wrong_frame = True
        else:
            unmatched_poss.remove(smallest_poss)
    if not wrong_frame:
        match = True
    return match

def frame_structure_exists(frames, searched_frame):
    exists = False
    for frame in frames:
        if have_same_structure(frame, searched_frame):
            exists = True
            break
    return exists 

# sprawdza czy dwa schematy posiadaj taka sama strukture, nie uwzglednia charakterystyk schematu
def have_same_structure(frame1, frame2):
    same_structure = True
    if (frame1.positions.count() == frame2.positions.count()):
        for pos1 in frame1.positions.all():
            pos_match = False
            for pos2 in frame2.positions.all():
                if have_same_positions_structure(pos1, pos2):
                    pos_match = True
                    break
            if not pos_match:
                same_structure = False
                break
    else:
        same_structure = False
    return same_structure              
            
def have_same_positions_structure(pos1, pos2):
    same_structure = False
    pos1_args = Counter(pos1.arguments.all())
    pos2_args = Counter(pos2.arguments.all())
    pos1_cats = Counter(pos1.categories.all())
    pos2_cats = Counter(pos2.categories.all())
    if(pos1_args == pos2_args and pos1_cats==pos2_cats):
        same_structure = True
    return same_structure

def escape_regex(string):
    return string.replace('(', '\(').replace(')', '\)').replace('{', '\{').replace('}', '\}').replace('[', '\[').replace(']', '\]')
