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

import math
import copy
import re
import itertools
import os.path
from operator import itemgetter

from django.utils.simplejson import dumps as json_encode, loads as json_decode
from django.contrib.auth.models import User, Group
from django.core import serializers 

from common.js_to_obj import frameObjToSerializableDict, jsArgToObj, jsFrameToObj, jsPosToObj
from dictionary.common_func import escape_regex
from dictionary.convert_frames import frame_conversion
from dictionary.filtering import default_filter_rules, prepare_filter_form, \
                                 save_lemma_filters_and_get_schemata_filter_setup, \
                                 schemata_filter_options
from dictionary.models import Vocabulary, Lemma, Lemma_Status, Frame_Opinion, \
                              Frame_Opinion_Value, Frame, NKJP_Example, NKJP_ArgSelection, \
                              NKJP_Source, NKJP_Opinion, Position, \
                              PositionCategory, Argument, Argument_Model, \
                              Configuration, \
                              Frame_Characteristic, Frame_Char_Model, \
                              Frame_Char_Value, Message, Change, Old_Frame, \
                              B_Frame, Entry, \
                              sorted_default_frame_char_vals, XcpExample, \
                              POS, get_frame_char_and_its_value, get_frame_char_by_type_and_value_pk, \
                              sortFrameChars, sortArguments, sortPositions, \
                              get_or_create_position, get_schemata_by_type, pos_compatible
from dictionary.forms import AddPositionForm, FrameForm, Pos_Cat_Form, \
                             AddNkjpExampleForm, MessageForm, SortForm, \
                             SimilarLemmasNewForm, ChangeUserFunctionForm, \
                             ExampleOpinionForm, \
                             FrameConversionForm, CreatePositionForm, AssignPhraseologicFrameForm
from dictionary.saving import connect_example_operation, disconnect_all_examples_operations, \
                              get_semantic_operations, update_connections, reconnect_examples, \
                              disconnect_example_operation
                             
from common.decorators import render, ajax, AjaxError
from common.util import triple_arg_poss
from dictionary.filtering import filter_lemmas
from dictionary.validation import find_similar_frames, get_all_test_missing_frames, get_aspect_rel_lemmas, \
                                  get_wrong_aspect_frames, validate_B_frames, get_deriv_miss_frames_message, \
                                  validate_phraseology_binded_frames, validate_rule_5, \
                                  validate_examples_and_mark_errors, validate_schemas_and_mark_errors, \
                                  validate_schemata_for_semantics_and_mark_errors, \
                                  get_missing_aspects_msg, validate_same_positions_schemata

from semantics.models import LexicalUnitExamples, SemanticFrame

from wordnet.models import LexicalUnit
                                  
from settings import PROJECT_PATH

# czasowniki podobne
from django.db.models import Q
import operator
from django.db.models import Count

from django.core.validators import email_re
from accounts.models import UserSettings, UserStats, RealizedPhraseologyBinding, \
                            can_modify_phraseology_only, get_anon_profile

from ajax_jqgrid import JqGridAjax, default_sort_rules

import locale
locale.setlocale(locale.LC_ALL, 'pl_PL.UTF-8')

DEFAULT_SAVE_PATH = os.path.join(PROJECT_PATH, 'tmp')

def reverse(string):
  return string[::-1]

######### nkjp example modification #####################

@ajax(method='get')
def get_nkjp_dict_ids(request, source_str, opinion_str):  
  source_obj = NKJP_Source.objects.get(source=source_str)
  opinion_obj = NKJP_Opinion.objects.get(opinion=opinion_str)
  return {'source_id' : source_obj.pk,
          'opinion_id': opinion_obj.pk} 

def user_can_confirm(user, example, lemma):
  can_confirm = False
  approvers_count = lemma.entry_obj.pos.example_approvers_num 
  #Configuration.objects.get(selected_conf=True).example_approvers_num
  if(example.source.confirmation_required and example.approvers.count() < approvers_count 
     and user.has_perm('dictionary.confirm_example')):
    try:
      example.approvers.get(username=user.username)
    except:
      can_confirm = True  
  return can_confirm

@ajax(method='get')
def can_confirm_example(request, example_id, lemma_id):     
  if example_id < 0:
    return {'can_confirm': False}
  example = NKJP_Example.objects.get(id=example_id)
  lemma = Lemma.objects.get(id=lemma_id)
  can_confirm = user_can_confirm(request.user, example, lemma)
  return {'can_confirm': can_confirm}

@ajax(method='post')
def confirm_nkjp_example(request, example_id, lemma_id):   
  example = NKJP_Example.objects.get(id=example_id)
  example.approvers.add(request.user) 
  lemma = Lemma.objects.get(id=lemma_id)
  approvers_count = lemma.entry_obj.pos.example_approvers_num#
  #Configuration.objects.get(selected_conf=True).example_approvers_num
  if example.approvers.count() >= approvers_count:
    example.approved = True
    example.save()
  return {}

#####################################################
def prepareFrameTable(frame):
  max_arguments = 0
  number_of_positions = len(frame.positions.all())
  positions_list = frame.positions.all()
  rows = []
  rows.append([frame])
  rows.append([])
  for position in positions_list:
    #appending categories row
    rows[1].append(position)
    if max_arguments < len(position.arguments.all()):
      max_arguments = len(position.arguments.all())
  
  # appending table headers spans
  rows.append([])
  rows[2].append(number_of_positions) # colspan
  rows[2].append(max_arguments)       # rowspan
    
  #appending arguments rows
  arg_number = 0
  for row_number in range(3, max_arguments+3):
    rows.append([])
    for position in positions_list:
      try:
        rows[row_number].append(position.arguments.all()[arg_number])
      except IndexError: 
        rows[row_number].append('None')
    arg_number = arg_number + 1
    
  return rows 

def nkjpExamplesObjToJs(nkjp_examples, user, lemma):    
  example_dict_list = []
  lexical_units = lemma.entry_obj.meanings.all()
  for example in nkjp_examples:
    frame = example.frame;
    frame_table_id = 'frame_'+str(frame.id)+'_'
    arguments_ids = []
    for argument_selections in example.arguments.all():
      position = argument_selections.position
      pos_table_id = 'pos_'+str(position.id)+'_'
      for argument in argument_selections.arguments.all():
        arguments_ids.append(frame_table_id+pos_table_id+'arg_'+str(argument.id)+'_')

    confirmed = True
    approvers_count = lemma.entry_obj.pos.example_approvers_num 
    if example.source.confirmation_required and example.approvers.count() < approvers_count:
      try:
        example.approvers.get(username=user.username)
      except:
        confirmed = False
        
    sentence = example.sentence
    comment = example.comment
        
    example_dict = { 'example_id'    : example.id,
                     'frame_id'      : frame_table_id,
                     'arguments_ids' : arguments_ids,
                     'sentence'      : sentence,
                     'source'        : example.source.source,
                     'opinion'       : example.opinion.opinion,
                     'comment'       : comment,
                     'confirmed'     : confirmed,
                     'semantic'      : example.semantic,
                     'lexical_unit'  : get_example_lexical_unit_id(lexical_units, example)} 
    example_dict_list.append(example_dict)
    
  return example_dict_list

def get_example_lexical_unit_id(lexical_units, example):
    unit_id = -1
    for lex_unit in lexical_units:
        if LexicalUnitExamples.objects.filter(example=example,
                                              lexical_unit=lex_unit).exists():
            unit_id = lex_unit.id
            break
    return unit_id

def nkjpLemmaExamplesObjToJs(nkjp_examples, user, lemma):
  example_dict_list = []
  for example in nkjp_examples:   
    confirmed = True
    approvers_count = lemma.entry_obj.pos.example_approvers_num
    if example.source.confirmation_required and example.approvers.count() < approvers_count:
      try:
        example.approvers.get(username=user.username)
      except:
        confirmed = False  
    
    sentence = example.sentence
    comment = example.comment
#    sentence = example.sentence.replace('\\', '\\\\').replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t").replace("\"", "\\\"")
#    comment = example.comment.replace('\\', '\\\\').replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t").replace("\"", "\\\"")
#    h = HTMLParser.HTMLParser()
#    sentence = h.unescape(sentence)
#    comment = h.unescape(comment)
    
    example_dict = { 'example_id'    : example.id,
                     'frame_id'      : '',
                     'arguments_ids' : [],
                     'sentence'      : sentence,
                     'source'        : example.source.source,
                     'opinion'       : example.opinion.opinion,
                     'comment'       : comment,
                     'confirmed'     : confirmed,
                     'semantic'      : False,
                     'lexical_unit'  : -1} 
    example_dict_list.append(example_dict)
    
  return example_dict_list
   
@render('old_frames.html')
@ajax(method='get', encode_result=False)
def get_old_frames(request, id):
  selected_lemma = Lemma.objects.get(id=id)
  old_frames = selected_lemma.old_frames
  reflexed_frames = []
  nreflexed_frames = []
  for frame in old_frames.all():
    if frame.reflex:
      reflexed_frames.append(frame)
    else:
      nreflexed_frames.append(frame)
  return {'reflexed_frames'  : reflexed_frames,
          'nreflexed_frames' : nreflexed_frames,
          'lemma_entry'      : selected_lemma.entry}

@ajax(method='get')
def user_has_perm(request, perm):
    has_perm = False
    if request.user.has_perm(perm) or request.user.is_superuser:
        has_perm = True
    return {'has_perm': has_perm}

# czy wybrany uzytkownik moze edytowac dane haslo
def user_can_modify(lemma_obj, req_user):
  can_modify = False
  try:
    lemma_obj.vocabulary.editors.get(username=req_user.username)
    edit_vocabulary = True
  except:
    edit_vocabulary = False
  if ( (lemma_obj.owner == req_user or req_user.has_perm('dictionary.change_all_lemmas') or 
        lemma_obj.phraseologist == req_user or lemma_obj.semanticist == req_user)
      and edit_vocabulary 
      and (req_user.has_perm('dictionary.add_phraseologic_frames') or 
           req_user.has_perm('dictionary.add_syntactic_frames') or
           req_user.has_perm('dictionary.add_semantic_frames'))
      and req_user.groups.all()[0].group_settings.active_statuses.filter(pk=lemma_obj.status.pk).exists()): 
    can_modify = True
  return can_modify

@ajax(method='get')
def get_arg_id(request, text_rep):
    argument = Argument.objects.get(text_rep=text_rep)
    arg_id = argument.id
    return {'arg_id': arg_id}

@render('lemma_preview.html')
@ajax(method='get', encode_result=False)
def get_lemma_preview(request, id, main_lemma_id):
  selected_lemma = Lemma.objects.get(id=id)  

  frame_char_models = Frame_Char_Model.objects.order_by('priority')
  frame_char_prior_model_vals = frame_char_models[0].frame_char_values.all()
  
  frame_char_list = []
  for frame_char_val in frame_char_prior_model_vals:
    frame_char_list.append(frame_char_val.value)
    
  json_frame_char_list = json_encode(frame_char_list)
  
  similarLemmasNewForm = SimilarLemmasNewForm(statuses=Lemma_Status.objects.order_by('priority'))

  return {'frame_char_list': json_frame_char_list,
          'selected_lemma': selected_lemma,
          'similarLemmasNewForm': similarLemmasNewForm}
  
@ajax(method='get')
def get_frame_filter_options(request):
  return schemata_filter_options()

@render('lemma_desc.html')
@ajax(method='get', encode_result=False)
def get_lemma_desc(request, id):
    system_conf = Configuration.objects.get(selected_conf=True)
    lemma = Lemma.objects.get(id=id)
    css_class = 'normal'
    if (lemma.frequency_1M < system_conf.min_1M_freq and 
        lemma.frequency_300M < system_conf.min_300M_freq):
        css_class = 'temporary'
    return {'lemma'    : lemma,
            'css_class': css_class}

@render('new_frames.html')
@ajax(method='get', encode_result=False)
def get_new_frames(request, id): 
    selected_lemma = Lemma.objects.get(id=id)  
    can_modify = user_can_modify(selected_lemma, request.user) 
    add_nkjp_form = AddNkjpExampleForm()
    return {'add_nkjp_form': add_nkjp_form,
            'can_modify': can_modify,
            'selected_lemma': selected_lemma,
            'skladnica_examples': selected_lemma.skladnica_frames.exists(),
            'xcp_examples': selected_lemma.entry_obj.xcp_examples.exists()}
  
  
@ajax(method='get', encode_result=True)
def get_ctrl_preview(request, id):
  change_obj = Change.objects.get(id=id)
  frames = change_obj.entry.frames.all()
  serialized_frames = []
  for frame in frames:
    serialized_frames.append(frameObjToSerializableDict(change_obj.entry, frame))
  return {'serialized_frames': serialized_frames}

@render('lemma_examples.html')
@ajax(method='get', encode_result=False)
def get_lemma_examples(request, id): 
  selected_lemma = Lemma.objects.get(id=id)  
#  lemma_nkjp_examples = selected_lemma.lemma_nkjp_examples.order_by('source__priority', 
#                                                                    'opinion__priority', 
#                                                                    'sentence')
#  lemma_nkjp_examples_js = nkjpLemmaExamplesObjToJs(lemma_nkjp_examples, request.user, selected_lemma)
  # sprawdz czy uzytkownik jest wlascicielem wybranego hasla
  can_modify = user_can_modify(selected_lemma, request.user)
  #json_lemma_nkjp_examples = json_encode(lemma_nkjp_examples_js)
  add_nkjp_form = AddNkjpExampleForm()

  return {'add_nkjp_form': add_nkjp_form,
          #'lemma_nkjp_examples': json_lemma_nkjp_examples,
          'can_modify': can_modify}

############################ lemma notes #################################
 
@render('lemma_notes.html')
@ajax(method='get', encode_result=False)
def get_lemma_notes(request, id):
  selected_lemma = Lemma.objects.get(id=id)
  add_note_form = MessageForm()
  messages = selected_lemma.messages.filter(private=False).order_by('-time')
  private_messages = Message.objects.none()
  if request.user.is_authenticated():
      private_messages = selected_lemma.messages.filter(sender=request.user, private=True).order_by('-time')
  return {'add_note_form': add_note_form,
          'messages': hide_message_duplicates(messages),
          'private_messages': private_messages}
  
def hide_message_duplicates(messages):
    visible_messages = []
    for message in messages.all():
        already_visible = False
        for vis_message in visible_messages:
            if (vis_message.topic == message.topic and
                vis_message.message_text == message.message_text and
                vis_message.sender == message.sender and
                vis_message.lemma == message.lemma and
                vis_message.private == message.private):
                already_visible = True
                break
        if not already_visible:
            visible_messages.append(message)
    return visible_messages 

@ajax(method='post')
def get_lemma_note(request, message_id):
    try:
        message_obj = Message.objects.get(id=message_id)
    except Message.DoesNotExist:
        raise AjaxError('already removed')
    return {'private'      : message_obj.private,
            'topic'        : message_obj.topic,
            'message_text' : message_obj.message_text}

@ajax(method='post')
def lemma_notes_form_submit(request, form_data):
    form_dict = dict((x['name'], x['value']) for x in form_data)
    if not (form_dict['topic'] and form_dict['message_text']):
        raise AjaxError('required fields not selected')
    selected_lemma = Lemma.objects.get(id=form_dict['lemma_id'])
    # nadawana jest notatka do hasla obrabianego frazeologicznie
    if selected_lemma.status.type.sym_name == 'initial':
        raise AjaxError('initial status')
    else:
        superphraseologists = Group.objects.get(name=u'Superfrazeolog').user_set.exclude(pk=request.user.pk).all()
        superlexicographers = Group.objects.get(name=u'Superleksykograf').user_set.exclude(pk=request.user.pk).all()
        supersemanticists = Group.objects.get(name=u'Supersemantyk').user_set.exclude(pk=request.user.pk).all()
        if selected_lemma.status.stage_of_work.sym_name == 'semantics':
            recipient = None
            if request.user != selected_lemma.semanticist:
                recipient = selected_lemma.semanticist
            if form_dict['private']:
                recipient = request.user
            Message(topic=form_dict['topic'], message_text=form_dict['message_text'],
                    sender=request.user, lemma=selected_lemma, private=form_dict['private'],
                    recipient=recipient).save()
            if not form_dict['private'] and not form_dict['is_ready_note']:
                for superlexicographer in superlexicographers:
                    Message(topic=form_dict['topic'], message_text=form_dict['message_text'],
                            sender=request.user, lemma=selected_lemma, private=form_dict['private'],
                            recipient=superlexicographer).save()
                for superphraseologist in superphraseologists:
                    Message(topic=form_dict['topic'], message_text=form_dict['message_text'],
                            sender=request.user, lemma=selected_lemma, private=form_dict['private'],
                            recipient=superphraseologist).save()                 
                if selected_lemma.status.type.sym_name == 'checked_s':
                    for supersemanticist in supersemanticists:
                        Message(topic=form_dict['topic'], message_text=form_dict['message_text'],
                                sender=request.user, lemma=selected_lemma, private=form_dict['private'],
                                recipient=supersemanticist).save()
        elif selected_lemma.status.stage_of_work.sym_name == 'phraseology':#selected_lemma.status.type.sym_name.endswith('_f'):
            recipient = None
            if request.user != selected_lemma.phraseologist:
                recipient = selected_lemma.phraseologist
            if form_dict['private']:
                recipient = request.user
            Message(topic=form_dict['topic'], message_text=form_dict['message_text'],
                    sender=request.user, lemma=selected_lemma, private=form_dict['private'],
                    recipient=recipient).save()
            if not form_dict['private'] and not form_dict['is_ready_note']:
                for superlexicographer in superlexicographers:
                    Message(topic=form_dict['topic'], message_text=form_dict['message_text'],
                            sender=request.user, lemma=selected_lemma, private=form_dict['private'],
                            recipient=superlexicographer).save()
                if selected_lemma.status.type.sym_name == 'checked_f':
                    for superphraseologist in superphraseologists:
                        Message(topic=form_dict['topic'], message_text=form_dict['message_text'],
                                sender=request.user, lemma=selected_lemma, private=form_dict['private'],
                                recipient=superphraseologist).save()
        elif selected_lemma.status.stage_of_work.sym_name == 'lexicography':
            recipient = None
            if request.user != selected_lemma.owner:
                recipient = selected_lemma.owner
            if form_dict['private']:
                recipient = request.user
            Message(topic=form_dict['topic'], message_text=form_dict['message_text'],
                    sender=request.user, lemma=selected_lemma, private=form_dict['private'],
                    recipient=recipient).save()
            if (selected_lemma.status.type.sym_name == 'checked' and 
                not form_dict['private'] and not form_dict['is_ready_note']):
                for superlexicographer in superlexicographers:
                    Message(topic=form_dict['topic'], message_text=form_dict['message_text'],
                            sender=request.user, lemma=selected_lemma, private=form_dict['private'],
                            recipient=superlexicographer).save()
    return {'id'   : selected_lemma.id,
            'entry': selected_lemma.entry}
  
@ajax(method='post')
def lemma_notes_modify(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  if not (form_dict['topic'] and form_dict['message_text']):
    raise AjaxError('required fields not selected')
  selected_lemma = Lemma.objects.get(id=form_dict['lemma_id'])
  message_obj = Message.objects.get(id=form_dict['message_id'])
  if not message_obj.private:
    raise AjaxError('not private')
  message_obj.topic = form_dict['topic']
  message_obj.message_text = form_dict['message_text']
  message_obj.private = form_dict['private']
  message_obj.save()
  return {'id'   : selected_lemma.id,
          'entry': selected_lemma.entry} 

@ajax(method='post')
def note_session_get(request):
    lemma_from_note_entry = None
    lemma_from_note_id = None
    if(request.session.has_key('lemma_from_note_entry') and
       request.session.has_key('lemma_from_note_id')):
        lemma_from_note_entry = request.session['lemma_from_note_entry']
        lemma_from_note_id = request.session['lemma_from_note_id']  
    return {'lemma_from_note_entry': lemma_from_note_entry,
            'lemma_from_note_id'   : lemma_from_note_id} 

####################################### end lemma notes ######################################

@ajax(method='post')
def restore_lemma(request, change_id, lemma_id):
  try:
    old_object = Lemma.objects.get(id=lemma_id, old=False)
  except Lemma.DoesNotExist:
    raise AjaxError('old version')
    
  old_object.old = True
  old_object.save()
  
  new_actual_lemma = Change.objects.get(id=change_id).entry
  new_actual_lemma.old = False
  new_actual_lemma.owner = old_object.owner
  new_actual_lemma.phraseologist = old_object.phraseologist
  new_actual_lemma.semanticist = old_object.semanticist
  new_actual_lemma.status = old_object.status
  new_actual_lemma.save()

  # tworzenie zmiany do systemu kontroli zmian
  lemma_change = Change(user=request.user, entry=old_object, act_owner=old_object.owner)
  lemma_change.save()
  
  # przepisywanie starych wersji dla kontroli zmian i dodanie nowej
  # najpier nalezy z przywrcanego hasla odpiac stare wpisy
  for version in old_object.old_versions.all():
    new_actual_lemma.old_versions.add(version)
  new_actual_lemma.old_versions.add(lemma_change)
  
  # przepisywanie historii zmian statusow
  for status_change in old_object.status_history.all():
    new_actual_lemma.status_history.add(status_change)
  
  # przepisywanie wiadomosci, wiadomosci powinny pozostawac bez zmian
  for message in old_object.messages.all():
    new_actual_lemma.messages.add(message)
           
  return {'id' : new_actual_lemma.id,
          'entry': new_actual_lemma.entry}

@render('change_ctrl.html')
@ajax(method='get', encode_result=False)
def get_change_ctrl(request, id):
  selected_lemma = Lemma.objects.get(id=id)  
  old_versions = selected_lemma.old_versions.order_by('-time')
  can_modify = (user_can_modify(selected_lemma, request.user) and 
                selected_lemma.status.stage_of_work.sym_name != 'semantics')
  return {'old_versions': old_versions,
          'can_modify': can_modify}

def getFrequentPositions(lead_number):
    freq_positions_tab = []
    max_pos_length = 0;
    positions = Position.objects.annotate(pos_count=Count('frames'))
    for position in positions.all():
        try:
            pos_index =  map(itemgetter('text_rep'), freq_positions_tab).index(position.text_rep)
            freq_positions_tab[pos_index]['freq'] += position.pos_count
        except ValueError:
            freq_positions_tab.append({'text_rep': position.text_rep,
                                       'freq': position.pos_count,
                                       'position': position}) 
            if len(position.text_rep) > max_pos_length:
                max_pos_length = len(position.text_rep)     
    freq_positions_tab.sort(key=lambda x:x['freq'], reverse=True)
    freq_positions_tab = freq_positions_tab[:lead_number]
    pos_objs_tab = []
    for position in freq_positions_tab:
        pos_objs_tab.append(position['position'])  
    return  {'positions': pos_objs_tab,
             'max_pos_length': max_pos_length}

@render('position_form.html')
@ajax(method='post', encode_result=False)
def position_form(request, lemma_id, phraseologic=False):
  freq_pos_objs = request.session['frequent_positions']
  freq_pos_str_tup = [(None, u'----------')]
  # TODO dodano wykluczenie najczesciej wykorzystywane pozycje
  entry = Lemma.objects.get(id=lemma_id).entry_obj
  pos_tag = entry.pos.tag
  if pos_tag == 'verb' and not phraseologic:
      for pos in freq_pos_objs['positions']:
        freq_pos_str_tup.append((pos, pos.text_rep));
  form = AddPositionForm(freq_pos=freq_pos_str_tup, 
                         pos_length=freq_pos_objs['max_pos_length'], 
                         pos_tag=pos_tag,
                         phraseologic_frame=phraseologic)   
  return {'form': form}

@render('create_position_form.html')
@ajax(method='post', encode_result=False)
def create_position_form(request, position_id=None):
    category = None
    arguments = []
    if position_id:
        edited_position = Position.objects.get(id=position_id)
        arguments = sortArguments(edited_position.arguments.all())
        try:
            category = edited_position.categories.get(control=False)
        except PositionCategory.DoesNotExist:
            pass
    form = CreatePositionForm(category=category)   
    return {'form': form,
            'arguments': arguments}

@ajax(method='post')
def create_position_form_submit(request, form_data):
    form_dict = dict((x['name'], x['value']) for x in form_data)
    categories = []
    if not form_dict['arguments']:
        raise AjaxError('no arguments')
    if form_dict['category']:
        category = PositionCategory.objects.get(pk=form_dict['category'])
        categories = [category]
    arguments = Argument.objects.filter(pk__in=form_dict['arguments'])
    arguments = sortArguments(arguments)
    position = get_or_create_position(categories=categories, 
                                      arguments=arguments)
    return {'id': position.id,
            'text_rep': position.text_rep}

@ajax(method='get')
def can_add_position_category(request, lemma_id):
    can_add_category = False
    lemma_obj = Lemma.objects.get(pk=lemma_id)
    lemma_pos = Entry.objects.get(name=lemma_obj.entry).pos
    if PositionCategory.objects.filter(poss=lemma_pos).exists():
        can_add_category = True
    return {'can_add_category': can_add_category}

@render('pos_cat_form.html')
@ajax(method='get', encode_result=False)
def pos_cat_form(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  category_obj = None
  control_objs = []
  for cat in form_dict['categories']:
    pos_cat_obj = PositionCategory.objects.get(category=cat)
    if pos_cat_obj.control:
      control_objs.append(pos_cat_obj.pk)
    elif not pos_cat_obj.control:
      category_obj = pos_cat_obj
      
  lemma = Lemma.objects.get(id=form_dict['lemma_id'])
  lemma_pos = lemma.entry_obj.pos
  
  form = Pos_Cat_Form(part_of_speech=lemma_pos, 
                      category_val=category_obj, 
                      control_val=control_objs)   
  return {'form': form}

@render('sort_form.html')
@ajax(method='get', encode_result=False)
def sort_form(request):
  if request.session.has_key('lemma_preview') and request.session['lemma_preview']:
    sort_rules = request.session['sort_rules_lemma_preview']
  else:
    sort_rules = request.session['sort_rules']
  form = SortForm(id_order_choice=sort_rules['id']['sort_order'], 
                  id_priority_choice=sort_rules['id']['priority'], 
                  entry_order_choice=sort_rules['entry']['sort_order'], 
                  entry_priority_choice=sort_rules['entry']['priority'],
                  owner_order_choice=sort_rules['owner']['sort_order'], 
                  owner_priority_choice=sort_rules['owner']['priority'],
                  phraseologist_order_choice=sort_rules['phraseologist']['sort_order'], 
                  phraseologist_priority_choice=sort_rules['phraseologist']['priority'],
                  semanticist_order_choice=sort_rules['semanticist']['sort_order'], 
                  semanticist_priority_choice=sort_rules['semanticist']['priority'],
                  vocabulary_order_choice=sort_rules['vocabulary']['sort_order'], 
                  vocabulary_priority_choice=sort_rules['vocabulary']['priority'],
                  status_order_choice=sort_rules['status']['sort_order'], 
                  status_priority_choice=sort_rules['status']['priority'])
  return {'form': form} 

@ajax(method='post')
def sort_form_submit(request, form_data):
  sort_dict = dict((x['name'], x['value']) for x in form_data)
  if not (sort_dict['id']['priority'] or sort_dict['entry']['priority'] or
          sort_dict['owner']['priority'] or sort_dict['phraseologist']['priority'] or
          sort_dict['semanticist']['priority'] or sort_dict['vocabulary']['priority'] or
          sort_dict['status']['priority']):
    raise AjaxError('none priority selected')
  sort_rules = {'id' : sort_dict['id'],
                'entry': sort_dict['entry'],
                'owner': sort_dict['owner'],
                'phraseologist': sort_dict['phraseologist'],
                'semanticist': sort_dict['semanticist'],
                'vocabulary': sort_dict['vocabulary'],
                'status': sort_dict['status']}
  if request.session.has_key('lemma_preview') and request.session['lemma_preview']:
    request.session['sort_rules_lemma_preview'] = sort_rules
  else:
    request.session['sort_rules'] = sort_rules
  ordered_sort_rules = order_sort_rules(sort_rules)
  return {'column': ordered_sort_rules[0]['name'],
          'sort_order': ordered_sort_rules[0]['rules']['sort_order']}

@ajax(method='get')
def get_sort_order(request):
  order = ''
  main_field = ''
  if request.session.has_key('lemma_preview') and request.session['lemma_preview']:
      if not request.session.has_key('sort_rules_lemma_preview'):
          request.session['sort_rules_lemma_preview'] = default_sort_rules()
      ordered_sort_rules = order_sort_rules(request.session['sort_rules_lemma_preview'])
      order = ordered_sort_rules[0]['rules']['sort_order']
      main_field = ordered_sort_rules[0]['name']
  else:
      if not request.session.has_key('sort_rules'):
          request.session['sort_rules'] = default_sort_rules()
      ordered_sort_rules = order_sort_rules(request.session['sort_rules'])
      order = ordered_sort_rules[0]['rules']['sort_order']
      main_field = ordered_sort_rules[0]['name']
  return {'order': order,
          'main_field': main_field}

@render('filter_form.html')
@ajax(method='get', encode_result=False)
def filter_form(request):
    return prepare_filter_form(request) 

@ajax(method='post')
def filter_form_submit(request, form_data):
    filter_dict = dict((x['name'], x['value']) for x in form_data)
    schemata_filter_options = save_lemma_filters_and_get_schemata_filter_setup(request, filter_dict)
    return schemata_filter_options

@ajax(method='post')
def save_columns(request, col_model, col_names, remap):
  request.session['colModel'] = col_model
  request.session['colNames'] = col_names
  request.session['remap'] = remap
  return {}

@ajax(method='get')
def sort_column(request, colName, sortOrder):
    if request.session.has_key('lemma_preview') and request.session['lemma_preview']:
        request.session['sort_rules_lemma_preview'] = clear_sort_rules()
        request.session['sort_rules_lemma_preview'][colName]['priority'] = 1
        request.session['sort_rules_lemma_preview'][colName]['sort_order'] = sortOrder
    else:
        request.session['sort_rules'] = clear_sort_rules()
        request.session['sort_rules'][colName]['priority'] = 1
        request.session['sort_rules'][colName]['sort_order'] = sortOrder
    return {}

def clear_sort_rules():
    id_rules = { 'priority': None,
                 'sort_order': 'desc'}
    entry_rules = { 'priority': None,
                    'sort_order': 'asc'}
    owner_rules = { 'priority': None,
                    'sort_order': 'desc'}
    phraseologist_rules = { 'priority': None,
                            'sort_order': 'desc'}
    semanticist_rules = { 'priority': None,
                          'sort_order': 'desc'}
    vocabulary_rules = { 'priority': None,
                         'sort_order': 'desc'}
    status_rules = { 'priority': None,
                     'sort_order': 'desc'}
    return {'id' : id_rules,
            'entry': entry_rules,
            'owner': owner_rules,
            'phraseologist': phraseologist_rules,
            'semanticist': semanticist_rules,
            'vocabulary': vocabulary_rules,
            'status': status_rules}

#################### relate entries ########################
@ajax(method='get')
def are_new_preview_entries_related(request, lemma_id, preview_lemma_id):
    related = False
    error, lemma, preview_lemma = check_if_selected_and_get(lemma_id, preview_lemma_id)
    if not error:
        related = are_entries_related(lemma, preview_lemma)
    return {'related': related}
    
def check_if_selected_and_get(lemma_id, preview_lemma_id):
    error = ''
    lemma = None
    preview_lemma = None
    try:
        lemma = Lemma.objects.get(id=lemma_id)
        preview_lemma = Lemma.objects.get(id=preview_lemma_id)
    except Lemma.DoesNotExist:
        error = 'lemma not selected'
    return error, lemma, preview_lemma

def are_entries_related(lemma, preview_lemma):
    related = False
    lemma_entry, preview_lemma_entry = get_entries(lemma, preview_lemma)
    if (lemma_entry.rel_entries.filter(id=preview_lemma_entry.id).exists() or
        preview_lemma_entry.rel_entries.filter(id=lemma_entry.id).exists()):
        related = True
    return related

def get_entries(lemma, preview_lemma):
    lemma_entry = lemma.entry_obj
    preview_lemma_entry = preview_lemma.entry_obj
    return lemma_entry, preview_lemma_entry

@ajax(method='post')
def relate_entries(request, lemma_id, preview_lemma_id):
    error, lemma, preview_lemma = check_if_selected_and_get(lemma_id, preview_lemma_id)
    if not error:
        error = check_if_can_relate(lemma, preview_lemma)
    if not error:
        error = check_if_has_rights_to_relate(lemma, request.user)
    if error:
        raise AjaxError(error)
    else:
        add_entries_relation(lemma, preview_lemma)
    return {}

def check_if_can_relate(lemma, preview_lemma):
    error = ''
    if lemma.id == preview_lemma.id:
        error = 'same lemma id'
    elif lemma.entry_obj.pos.tag == preview_lemma.entry_obj.pos.tag:
        error = 'same part of speech' 
    return error

def check_if_has_rights_to_relate(lemma, user):
    error = ''
    if not user_can_modify(lemma, user):
        error = 'can not edit'
    return error

def add_entries_relation(lemma, preview_lemma):
    lemma_entry, preview_lemma_entry = get_entries(lemma, preview_lemma)
    lemma_entry.rel_entries.add(preview_lemma_entry)
    preview_lemma_entry.rel_entries.add(lemma_entry)

@ajax(method='post')
def disrelate_entries(request, lemma_id, preview_lemma_id):
    error, lemma, preview_lemma = check_if_selected_and_get(lemma_id, preview_lemma_id)
    if not error:
        error = check_if_has_rights_to_relate(lemma, request.user)
    if not error:
        error = check_if_share_sematic_frames(lemma, preview_lemma)
    if error:
        raise AjaxError(error)
    else:
        cancel_entries_relation(request, lemma, preview_lemma)
    return {}

def check_if_share_sematic_frames(lemma, preview_lemma):
    error = ''
    lemma_visible_frames = lemma.entry_obj.visible_frames()
    preview_visible_frames = preview_lemma.entry_obj.visible_frames()

    if (lemma_visible_frames.filter(pk__in=preview_visible_frames).exists() or
        preview_visible_frames.filter(pk__in=lemma_visible_frames).exists()):
        error = 'shared frames'
    return error

def cancel_entries_relation(request, lemma, preview_lemma):
    lemma_entry, preview_lemma_entry = get_entries(lemma, preview_lemma)
    lemma_entry.rel_entries.remove(preview_lemma_entry)
    preview_lemma_entry.rel_entries.remove(lemma_entry)

#############################################################
@render('skladnica_examples.html')
@ajax(method='get', encode_result=False)
def show_skladnica_examples(request, id):
    examples = []
    if id:
        main_frame = Old_Frame.objects.get(pk=id)
        examples.append({'id'             : main_frame.example.id, 
                         'sentence'       : main_frame.example.sentence,
                         'wrong_example'  : main_frame.wrong_example})
        sub_frames = main_frame.sub_frames.order_by('old_frame_value')
        for frame in sub_frames.all():
            examples.append({'id'             : frame.example.id, 
                             'sentence'       : frame.example.sentence,
                             'wrong_example'  : frame.wrong_example})
    return {'examples': examples}
    
@render('example_opinion_form.html')
@ajax(method='get', encode_result=False)
def example_opinion_form(request, example_id):
    example = NKJP_Example.objects.get(id=example_id)
    is_wrong = example.skladnica_frame.wrong_example
    example_opinion_form = ExampleOpinionForm(is_wrong=is_wrong)   
    return {'example_opinion_form': example_opinion_form,
            'example'             : example}

@ajax(method='post')
def example_opinion_form_submit(request, form_data):
    form_dict = dict((x['name'], x['value']) for x in form_data)
    skladnica_frame = NKJP_Example.objects.get(id=form_dict['example']).skladnica_frame
    skladnica_frame.wrong_example = form_dict['is_wrong']
    skladnica_frame.save()
    return {}

def possible_args_to_pos_lists(possibilities):
    positions_objs = []
    for arg_poss in possibilities:
        if arg_poss.position_category:
            pos_text_rep = '%s{%s}' % (arg_poss.position_category.category, arg_poss.argument.text_rep)
        else:
            pos_text_rep = '{%s}' % (arg_poss.argument.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_poss.argument)
            if arg_poss.position_category:
                pos_obj.categories.add(arg_poss.position_category)
        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 poss_args_to_frame(poss_args, reflex, negativity, predicativity, aspect):
    sort_pos_str_tab, positions_objs = possible_args_to_pos_lists(poss_args)
    frame_char_vals = []
    for char_val in sorted_default_frame_char_vals():
        if reflex and char_val.frame_char_models.all()[0].model_name == u'ZWROTNOŚĆ':
            frame_char_vals.append(Frame_Char_Value.objects.get(frame_char_models__model_name=u'ZWROTNOŚĆ',
                                                                value=u'się'))
        elif char_val.frame_char_models.all()[0].model_name == u'ASPEKT':
            frame_char_vals.append(aspect.value)
        elif char_val.frame_char_models.all()[0].model_name == u'NEGATYWNOŚĆ':
            frame_char_vals.append(negativity.value)
        elif char_val.frame_char_models.all()[0].model_name == u'PREDYKATYWNOŚĆ':
            frame_char_vals.append(predicativity.value)
        else:
            frame_char_vals.append(char_val)
    frame_char_vals_str_ls = list([char_val.value 
                                   for char_val in frame_char_vals])  
    frame_text_rep = u'%s:%s' % (':'.join(frame_char_vals_str_ls), 
                                  '+'.join(sort_pos_str_tab))
    try: 
        frame_obj = Frame.objects.get(text_rep=frame_text_rep)
    except Frame.DoesNotExist:
        frame_obj = Frame(text_rep=frame_text_rep)
        frame_obj.save()
        frame_obj.positions.add(*positions_objs)
        for char_val in frame_char_vals:
            frame_obj.characteristics.add(Frame_Characteristic.objects.get(value=char_val))
        if frame_obj.has_phraseologic_arguments():
            frame_obj.phraseologic = True
            frame_obj.save()
    return frame_obj 

@render('frame_realizations.html')
@ajax(method='post', encode_result=False)
def show_frame_realizations(request, id, propose_type):
    realizations = []
    if id:
        if propose_type == 'skladnica':
            tmp_possibilites = []
            possibilities = []
            main_frame = Old_Frame.objects.get(pk=id)
            if main_frame.reflex:
                for skladnica_arg in main_frame.arguments.all():
                    tmp_possibilites.append(skladnica_arg.possible_args.all())
                if not main_frame.arguments.exists():
                    tmp_possibilites.append(triple_arg_poss('np(str)', ['subj']) +
                                            triple_arg_poss('E', ['subj']))
                possibilities = copy.deepcopy(tmp_possibilites)
                tmp_possibilites.append(triple_arg_poss('refl', ['', 'obj']))
                
                for element in itertools.product(*tmp_possibilites):
                    frame_obj = poss_args_to_frame(element, False, 
                                                   Frame_Characteristic.objects.get(type=u'NEGATYWNOŚĆ', value__value=u'_'),
                                                   Frame_Characteristic.objects.get(type=u'PREDYKATYWNOŚĆ', value__value=u''), 
                                                   Frame_Characteristic.objects.get(type=u'ASPEKT', value__value=u'_'))
                    if validate_rule_5(frame_obj):
                        realizations.append(frame_obj)
                    
                for element in itertools.product(*possibilities):
                    frame_obj = poss_args_to_frame(element, True, 
                                                   Frame_Characteristic.objects.get(type=u'NEGATYWNOŚĆ', value__value=u'_'),
                                                   Frame_Characteristic.objects.get(type=u'PREDYKATYWNOŚĆ', value__value=u''), 
                                                   Frame_Characteristic.objects.get(type=u'ASPEKT', value__value=u'_'))    
                    if validate_rule_5(frame_obj):
                        realizations.append(frame_obj)
            else:
                for skladnica_arg in main_frame.arguments.all():
                    possibilities.append(skladnica_arg.possible_args.all())
                for element in itertools.product(*possibilities):
                    frame_obj = poss_args_to_frame(element, False, 
                                                   Frame_Characteristic.objects.get(type=u'NEGATYWNOŚĆ', value__value=u'_'),
                                                   Frame_Characteristic.objects.get(type=u'PREDYKATYWNOŚĆ', value__value=u''), 
                                                   Frame_Characteristic.objects.get(type=u'ASPEKT', value__value=u'_'))
                    if validate_rule_5(frame_obj):
                        realizations.append(frame_obj)    
        elif propose_type == 'B':  
            tmp_possibilites = []
            possibilities = []
            main_frame = B_Frame.objects.get(pk=id) 
            if main_frame.reflex:
                for B_arg in main_frame.arguments.all():
                    tmp_possibilites.append(B_arg.possible_args.all())
                possibilities = copy.deepcopy(tmp_possibilites)
                tmp_possibilites.append(triple_arg_poss('refl', ['', 'obj']))
                
                for element in itertools.product(*tmp_possibilites):
                    frame_obj = poss_args_to_frame(element, False, 
                                                   main_frame.negativity, 
                                                   Frame_Characteristic.objects.get(type=u'PREDYKATYWNOŚĆ', value__value=u''),
                                                   main_frame.aspect)
                    if validate_rule_5(frame_obj):
                        realizations.append(frame_obj)
                    
                for element in itertools.product(*possibilities):
                    frame_obj = poss_args_to_frame(element, True, 
                                                   main_frame.negativity, 
                                                   Frame_Characteristic.objects.get(type=u'PREDYKATYWNOŚĆ', value__value=u''),
                                                   main_frame.aspect)    
                    if validate_rule_5(frame_obj):
                        realizations.append(frame_obj)
            else:
                for B_arg in main_frame.arguments.all():
                    possibilities.append(B_arg.possible_args.all())
                for element in itertools.product(*possibilities):
                    frame_obj = poss_args_to_frame(element, False, 
                                                   main_frame.negativity, 
                                                   Frame_Characteristic.objects.get(type=u'PREDYKATYWNOŚĆ', value__value=u''),
                                                   main_frame.aspect)
                    if validate_rule_5(frame_obj):
                        realizations.append(frame_obj) 
        realizations.sort(key=operator.attrgetter('text_rep'))
    return {'realizations': realizations}

@ajax(method='post')
def send_miss_frames_msg(request, lemma_id, status_id):
    lemma_obj = Lemma.objects.get(id=lemma_id)
    status_obj = Lemma_Status.objects.get(id=status_id)
    if status_obj.type.sym_name == 'checked_f':
        aspect_rel_lemmas = get_aspect_rel_lemmas(lemma_obj)    
        for pattern_lemma in aspect_rel_lemmas:    
            miss_frames = get_miss_pattern_frames(lemma_obj, pattern_lemma) 
            msg_content = create_miss_pattern_frames_msg(lemma_obj, miss_frames)
            if msg_content:
                if pattern_lemma.status.type.sym_name == 'checked' or pattern_lemma.status.type.sym_name.endswith('_f'):
                    if (pattern_lemma.status.type.sym_name == 'checked' or 
                        (pattern_lemma.status.type.sym_name.endswith('_f') and contains_non_phraseologic_frames(miss_frames))):
                        superlexicographers = Group.objects.get(name=u'Superleksykograf').user_set.all()
                        for superlexicographer in superlexicographers:
                            Message(topic=u'Wiadomość automatyczna systemu Slowal - brakujące schematy',
                                    message_text=msg_content,
                                    sender=request.user,
                                    recipient=superlexicographer,
                                    lemma=pattern_lemma,
                                    private=False,
                                    new=True).save()   
                    if pattern_lemma.status.type.sym_name == 'checked_f' and contains_phraseologic_frames(miss_frames):
                        superphraseologists = Group.objects.get(name=u'Superfrazeolog').user_set.all()
                        for superphraseologist in superphraseologists:
                            Message(topic=u'Wiadomość automatyczna systemu Slowal - brakujące schematy',
                                    message_text=msg_content,
                                    sender=request.user,
                                    recipient=superphraseologist,
                                    lemma=pattern_lemma,
                                    private=False,
                                    new=True).save()
    return {}

def create_miss_pattern_frames_msg(test_lemma, frames_to_add):
    #frames_to_add = get_miss_pattern_frames(test_lemma, pattern_lemma)
    msg_content = ''
    if frames_to_add:
        msg_content = u'Hasło nie posiada następujących schematów z powiązanego aspektowo hasła %s:\n' % test_lemma.entry
        for frame in frames_to_add:
            msg_content += u'\t- %s\n' % frame.text_rep
        msg_content += u'\nZaleca się ponowne przejrzenie hasła.'  
    return msg_content 

def get_miss_pattern_frames(test_lemma, pattern_lemma):
    missing_frames = []
    for test_frame in test_lemma.frames.all():
        match_found = False
        test_reflex = test_frame.characteristics.get(type=u'ZWROTNOŚĆ')
        test_negativity = test_frame.characteristics.get(type=u'NEGATYWNOŚĆ')
        for pattern_frame in pattern_lemma.frames.filter(characteristics=test_reflex).filter(characteristics=test_negativity):
            wrong_frame = False
            unmatched_positions = pattern_frame.positions
            for position in test_frame.positions.all():
                pattern_positions = copy.deepcopy(unmatched_positions)
                if position.categories.exists():
                    for pos_cat in position.categories.all():
                        pattern_positions = pattern_positions.filter(categories__category=pos_cat)
                else:
                    pattern_positions = pattern_positions.filter(categories=None)
                for test_arg in position.arguments.all():
                    pattern_positions = pattern_positions.filter(arguments__text_rep=test_arg.text_rep)
                if pattern_positions.exists():
                    matching_pos = pattern_positions.annotate(args_count=Count('arguments')).order_by('args_count')[0]
                    unmatched_positions.exclude(pk=matching_pos.pk)
                else:
                    wrong_frame = True
                    break       
            if not wrong_frame:
                match_found = True
                break
        if not match_found:
            missing_frames.append(test_frame)
    return missing_frames

def contains_phraseologic_frames(frames):
    for frame in frames:
        if frame.has_phraseologic_arguments():
            return True
    return False

def contains_non_phraseologic_frames(frames):
    for frame in frames:
        if not frame.has_phraseologic_arguments():
            return True
    return False   

@render('aspect_rel_missing_frames.html')
@ajax(method='post', encode_result=False)  
def aspect_rel_missing_frames(request, lemma_id, frames, editable):
    lemma_obj = Lemma.objects.get(id=lemma_id)
    aspect_rel_lemmas = get_aspect_rel_lemmas(lemma_obj)    
    missing_frames = get_all_test_missing_frames(frames, aspect_rel_lemmas)  
    return {'missing_frames': missing_frames,
            'editable'      : editable}           

# charakterystyki ramek, hardcody
@ajax(method='post')  
def add_new_frames(request, form_data):  
    form_dict = dict((x['name'], x['value']) for x in form_data)
    new_frames = []
    lemma_obj = Lemma.objects.get(id=form_dict['lemma_id'])
    for frame_dict in form_dict['selected_frames']:
        frame = Frame.objects.get(id=frame_dict['frame'])
        new_aspect = Frame_Characteristic.objects.get(id=frame_dict['aspect'])
        serializable_frame = frameObjToSerializableDict(lemma_obj, frame)
        serializable_frame['characteristics'][list(Frame_Char_Model.objects.order_by('priority').values_list('model_name', flat=True)).index('ASPEKT')] = new_aspect.value.value 
        serializable_frame['opinion'] = Frame_Opinion_Value.objects.get(id=frame_dict['opinion']).value
        json_frame = json_encode(serializable_frame) 
        new_frames.append(json_frame)      
    return {'new_frames': new_frames}  

@ajax(method='get')
def need_conversion(request, from_lemma_id, to_lemma_id):
    can_be_converted = False
    need_conversion = False
    from_lemma = Lemma.objects.get(id=from_lemma_id)
    from_entry = from_lemma.entry_obj
    to_lemma = Lemma.objects.get(id=to_lemma_id)
    to_entry = to_lemma.entry_obj
    if not pos_compatible(from_entry.pos, to_entry.pos):
        need_conversion = True
    if conversion_possible(from_entry, to_entry):
        can_be_converted = True
    return {'can_be_converted': can_be_converted,
            'need_conversion': need_conversion}
    
def conversion_possible(from_entry, to_entry):
    can_be_converted = False
    if (to_entry.rel_entries.filter(pk=from_entry.pk).exists() and
        from_entry.pos.tag == 'verb' and 
        (to_entry.pos.tag == 'noun' or to_entry.pos.tag == 'adj')):
        can_be_converted = True
    elif (to_entry.rel_entries.filter(pk=from_entry.pk).exists() and
        from_entry.pos.tag == 'adj' and to_entry.pos.tag == 'noun'):
        can_be_converted = True
    return can_be_converted
        
@ajax(method='get')
def get_compatible_schema_chars(request, lemma_id, schema_id):
    schema_chars = []
    lemma = Lemma.objects.get(id=lemma_id)
    schema = Frame.objects.get(id=schema_id)
    schema_char_objs = sortFrameChars(schema.characteristics.all())
    
    if (not request.user.has_perm('dictionary.add_syntactic_frames') and 
        not request.user.is_superuser):
        for char in schema_char_objs:
            possible_values = get_frame_char_values(char.type, lemma, True)
            if possible_values.filter(id=char.value.id).exists():
                schema_chars.append(char.value.value)
            else:
                schema_chars.append(possible_values.all()[0].value)
    else:
        for char in schema_char_objs:
            possible_values = get_frame_char_values(char.type, lemma, False)
            if possible_values.filter(id=char.value.id).exists():
                schema_chars.append(char.value.value)
            else:
                schema_chars.append(possible_values.all()[0].value)
        
    return {'schema_chars': schema_chars}

@render('frame_conversion_form.html')
@ajax(method='post', encode_result=False)
def frame_conversion_form(request, from_lemma_id, to_lemma_id, frame_id):
    from_lemma = Lemma.objects.get(id=from_lemma_id)
    from_entry = Entry.objects.get(name=from_lemma.entry)
    to_lemma = Lemma.objects.get(id=to_lemma_id)
    to_entry = Entry.objects.get(name=to_lemma.entry)
    frame = Frame.objects.get(id=frame_id)
    frame_versions = frame_conversion(frame, from_entry.pos, to_entry.pos)
#    frame_versions = remove_existing_frames(to_lemma.frames.all(), frame_versions)
    frame_versions_ids = [frame.id for frame in frame_versions]
    frame_versions_query = Frame.objects.filter(id__in=frame_versions_ids).order_by('text_rep')
    conversion_form = FrameConversionForm(frame_versions=frame_versions_query)
    return {'frame_conversion_form': conversion_form}

@ajax(method='post')
def frame_conversion_form_submit(request, form_data):
    form_dict = dict((x['name'], x['value']) for x in form_data)
    if not form_dict['frame_version']:
        raise AjaxError('select frame version')
    lemma = Lemma.objects.get(id=form_dict['lemma_id'])
    frame_version = Frame.objects.get(id=form_dict['frame_version'])
    json_frame = json_encode(frameObjToSerializableDict(lemma, frame_version))
    return {'frame' : json_frame}

# posiada hardcody
@render('frame_form.html')
@ajax(method='post', encode_result=False)
def frame_form(request, form_data, phraseologic=False):
    form_dict = dict((x['name'], x['value']) for x in form_data)
    phraseologic_modify_only = can_modify_phraseology_only(request.user, phraseologic)  
    pos = POS.objects.get(tag='unk')
    skladnica_frames = None
    B_frames = None
    lemma = None
    phraseologic_propositions = Frame.objects.none()
    if form_dict['lemma_id']:
        lemma = Lemma.objects.get(pk=form_dict['lemma_id'])
        pos = lemma.entry_obj.pos
        if not form_dict['edit']:
            if phraseologic_modify_only:
                phraseologic_propositions = lemma.entry_obj.phraseologic_propositions
            else:
                skladnica_frames = lemma.skladnica_frames
                skladnica_frames = skladnica_frames.filter(visible=True)
                B_frames = lemma.B_frames
    
    frame_chars_order_ls = list(Frame_Char_Model.objects.order_by('priority').values_list('model_name', flat=True))
    aspect_values = get_frame_char_values(u'ASPEKT', lemma, phraseologic_modify_only)
    reflex_values = get_frame_char_values(u'ZWROTNOŚĆ', lemma, phraseologic_modify_only)
    neg_values = get_frame_char_values(u'NEGATYWNOŚĆ', lemma, phraseologic_modify_only)
    pred_values = get_frame_char_values(u'PREDYKATYWNOŚĆ', lemma, phraseologic_modify_only)
    
    try:
        curr_aspect_val = aspect_values.get(value=form_dict['characteristics'][frame_chars_order_ls.index(u'ASPEKT')])
    except:
        curr_aspect_val = get_default_char_value(aspect_values)
            
    try:
        curr_reflex_val = reflex_values.get(value=form_dict['characteristics'][frame_chars_order_ls.index(u'ZWROTNOŚĆ')])
    except:
        curr_reflex_val = get_default_char_value(reflex_values)
            
    try:
        curr_neg_val = neg_values.get(value=form_dict['characteristics'][frame_chars_order_ls.index(u'NEGATYWNOŚĆ')])
    except:
        curr_neg_val = get_default_char_value(neg_values)
        
    try:
        curr_pred_val = pred_values.get(value=form_dict['characteristics'][frame_chars_order_ls.index(u'PREDYKATYWNOŚĆ')])
    except:
        curr_pred_val = get_default_char_value(pred_values)
      
    if form_dict['opinion']: 
        frame_opinion = Frame_Opinion_Value.objects.get(value=form_dict['opinion'])
    else:
        frame_opinion = form_dict['opinion']
        
    form = FrameForm(aspect_values=aspect_values, 
                     reflex_values=reflex_values,
                     neg_values=neg_values,
                     pred_values=pred_values,
                     proposed_frames_skladnica=skladnica_frames,
                     proposed_frames_B=B_frames,
                     proposed_phraseology_frames=phraseologic_propositions,
                     aspect_val=curr_aspect_val, 
                     reflex_val=curr_reflex_val,
                     neg_val=curr_neg_val,
                     pred_val=curr_pred_val,
                     frame_opinion_val=frame_opinion,
                     pos=pos,
                     edit=form_dict['edit'],
                     phraseologic_modification=phraseologic_modify_only)
    
    return {'form': form}

def get_frame_char_values(char_type, lemma, phraseologic_modification=False):
    pos = POS.objects.get(tag='unk')
    if lemma:
        pos = lemma.entry_obj.pos
    frame_char_vals = Frame_Char_Model.objects.get(model_name=char_type).frame_char_values.filter(poss=pos).order_by('priority')
    if phraseologic_modification and not char_type == u'NEGATYWNOŚĆ':
        existing_char_vals = lemma.get_existing_frame_char_values(char_type)
        existing_char_vals_ids = [val.id for val in existing_char_vals]
        frame_char_vals = frame_char_vals.filter(id__in=existing_char_vals_ids)
    return frame_char_vals

def get_default_char_value(possibilities):
    value = None
    try:
        value = possibilities.get(default=True)  
    except Frame_Char_Value.DoesNotExist:
        value = possibilities.all()[0]
    return value   

def regex_query(string):
    q_query = []
    for alternative in string.split('|'):
        for conj in alternative.split('&'):
            try:
                conj = conj.strip()
                if conj.startswith('!'):
                    regex = ur'^%s$' % escape_regex(conj.lstrip('!'))
                    q_query.append(~Q(text_rep__regex=regex))
                else:
                    regex = ur'^%s$' % escape_regex(conj)
                    q_query.append(Q(text_rep__regex=regex))
            except:
                pass
    return q_query  

@ajax(method='get', encode_result=True)         
def position_lookup(request, term):
    results = []
    term = unicode(term)
    if len(term) > 0:
        try:
            model_results = Position.objects.filter(frames__lemmas__old=False)
            model_results = model_results.filter(reduce(operator.or_, regex_query(term)))
            model_results = model_results.order_by('text_rep').distinct()
            results = [ (unicode(x), x.id) for x in model_results ]
        except:
            pass
    return {'result': results}

@ajax(method='get', encode_result=True)         
def argument_lookup(request, term):
    results = []
    term = unicode(term)
    if len(term) > 0:
        try:
            model_results = Argument.objects.filter(positions__frames__lemmas__old=False)
            model_results = model_results.filter(reduce(operator.or_, regex_query(term)))
            model_results = model_results.order_by('text_rep').distinct()
            results = [ (unicode(x), x.pk) for x in model_results ]
        except:
            pass
    return {'result': results}

@ajax(method='post')
def add_position(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  result = {}
  # wybrano dwie pozycje, nalezy wybrac tylko jedna
  if form_dict['filtered_positions'] and form_dict['frequent_positions'] != 'None':
    raise AjaxError('not proper selection')
  # wybrano gotowa pozycje
  elif form_dict['frequent_positions'] != 'None' or form_dict['filtered_positions']:
    if form_dict['frequent_positions'] != 'None':
        pos_obj = Position.objects.filter(text_rep=form_dict['frequent_positions']).order_by('id')[0]
    elif form_dict['filtered_positions']:
      pos_objs = Position.objects.filter(text_rep=form_dict['filtered_positions'])
      if len(pos_objs) == 0:
        raise AjaxError('wrong position representation')
      pos_obj = pos_objs[0]
    json_serializer = serializers.get_serializer("json")()
    categories_str = json_serializer.serialize(pos_obj.categories.all(), ensure_ascii=False)
    arguments_str = json_serializer.serialize(pos_obj.arguments.all(), ensure_ascii=False)
    result = {"id": pos_obj.id,
              "text_rep": pos_obj.text_rep,
              "categories": categories_str,
              "arguments": arguments_str}
  else: # nie wybrano nic, dodawana jest pusta pozycja
    result = {"id": -1,
              "text_rep": '',
              "categories": '[]',
              "arguments": '[]'}
  return result
    

def sortByPriority(list):
  ret_list = []
  for elem in list:
    index = len(ret_list)
    for ret_elem in ret_list:
      if (ret_elem.priority>elem.priority):
        index = ret_list.index(ret_elem)
      elif(ret_list.index(ret_elem)==len(ret_list)):
        index = len(ret_list)
    ret_list.insert(index, elem)   
  return ret_list                                        

################################################ Phraseology #########################################

@ajax(method='get')
def arg_can_be_lexicalized(request, argument_id):
    can_be_lexicalized = False
    arg_obj = Argument.objects.get(id=argument_id)
    arg_model = Argument_Model.objects.get(arg_model_name=arg_obj.type)
    if arg_model.used_in_lex or arg_model.phraseologic:
        can_be_lexicalized = True
    return {'can_be_lexicalized': can_be_lexicalized}    

@ajax(method='get')
def phraseologic_propositions_exists(request, lemma_id):
    propositions_exists = False
    lemma = Lemma.objects.get(id=lemma_id)
    if lemma.entry_obj.phraseologic_propositions.exists():
        propositions_exists = True
    return {'propositions_exists': propositions_exists}

@render('assign_phraseologic_frame_form.html')
@ajax(method='post', encode_result=False)  
def assign_phraseologic_frame_form(request, lemma_id, phraseologic_frame):
    lemma = Lemma.objects.get(id=lemma_id)
    phraseologic_frame_obj = jsFrameToObj(phraseologic_frame, lemma.entry)
    #entry_obj = lemma.entry_obj  
    #entries_with_phraseology = Entry.objects.filter(phraseologic_propositions=phraseologic_frame_obj).order_by('name')
    entries_with_phraseology = get_entries_with_proposed_frame_struct(phraseologic_frame_obj).order_by('name')
    form = AssignPhraseologicFrameForm(phraseologic_frame=phraseologic_frame_obj) 
    return {'entries': entries_with_phraseology,
            'form': form}  
    
def get_entries_with_proposed_frame_struct(frame):
    frames = get_frames_with_exact_positions(frame.positions.all())
    entries = Entry.objects.filter(phraseologic_propositions__in=frames).distinct()
    return entries
        
def get_frames_with_exact_positions(positions):
    frames = Frame.objects.annotate(positions_count=Count('positions'))
    frames = frames.filter(phraseologic=True, positions_count=len(positions))
    for position in positions:
        frames = frames.filter(positions__text_rep=position.text_rep)
    return frames.all() 
    
@ajax(method='post')
def assign_phraseologic_frame(request, form_data, lemma_id):
    form_dict = dict((x['name'], x['value']) for x in form_data)
    main_entry = Lemma.objects.get(id=lemma_id).entry_obj
    error = assign_phraseologic_frame_form_validation(form_dict)
    if error:
        raise AjaxError(error)
    phraseologic_frame = Frame.objects.get(id=form_dict['phraseologic_frame'])
    entry = get_entry_to_add_phraseologic_frame(form_dict['entry'])
    if entry == main_entry:
        error = u'Edytowane hasło zostanie przypisane do frazeologizmu automatycznie po zmianie statusu na wyższy.'
        raise AjaxError(error)
    entries_with_phraseology = get_entries_with_proposed_frame_struct(phraseologic_frame)
    if entries_with_phraseology.filter(id=entry.id).exists():
        error = u'Schemat jest już przypisany do wybranego hasła.'
        raise AjaxError(error)
    if not entries_with_phraseology.filter(id=entry.id).exists():
        entry.phraseologic_propositions.add(phraseologic_frame)
        phraseology_binding = RealizedPhraseologyBinding(main_entry=main_entry,
                                                         binded_entry=entry,
                                                         phraseologic_frame=phraseologic_frame,
                                                         cash=1.0,
                                                         paid=False,
                                                         counted=False)
        phraseology_binding.save()
        request.user.user_stats.bind_phraseology_frames_history.add(phraseology_binding)
        send_phraseology_binding_message(request.user, main_entry, entry, phraseologic_frame)
    return {}

def assign_phraseologic_frame_form_validation(form_dict):
    error = ''
    phraseologic_frame = Frame.objects.get(id=form_dict['phraseologic_frame'])
    if not form_dict['entry']:
        error = u'Wybierz hasło.'
    elif not phraseologic_frame.has_phraseologic_arguments():
        error = u'Schemat, który chcesz przypisać, nie posiada argumentów frazeologicznych.'
    elif phraseologic_frame.has_inactive_arguments():
        error = u'Schemat, który chcesz przypisać, posiada nieaktywne typy argumentów.'
    else:
        error = entry_field_validation(form_dict['entry'])
    return error
    
def entry_field_validation(field_content):
    error = ''
    field_content_parts = field_content.split()
    if len(field_content_parts) != 2:
        error = u'Pole "Hasło" powinno zawierać wartość postaci: <lemat> <część mowy>.'
    else:
        entry_name = field_content_parts[0]
        pos_name = field_content_parts[1]
        try:
            pos = POS.objects.get(name=pos_name)
            try:
                Entry.objects.get(name=entry_name, pos=pos)
            except Entry.DoesNotExist:
                error = u'Wybrane hasło nie istnieje.'
        except POS.DoesNotExist:
            error = 'Wybrana część mowy nie istnieje.'
    return error

def get_entry_to_add_phraseologic_frame(field_content):
    field_content_parts = field_content.split()
    entry_name = field_content_parts[0]
    pos_name = field_content_parts[1]
    pos = POS.objects.get(name=pos_name)
    entry = Entry.objects.get(name=entry_name, pos=pos)
    return entry

def send_phraseology_binding_message(sender, main_entry, binded_entry, frame):
    binded_lemma = Lemma.objects.get(entry_obj=binded_entry, old=False)
    binded_lemma_status = binded_lemma.status
    if binded_lemma_status.type.sym_name == 'checked_f' or binded_lemma_status.stage_of_work.sym_name == 'semantics':
        msg_content = create_binding_message_content(main_entry, binded_entry, frame)
        superphraseologists = Group.objects.get(name=u'Superfrazeolog').user_set.all()
        for superphraseologist in superphraseologists:
            Message(topic=u'Wiadomość automatyczna systemu Slowal - przypisano schemat frazeologiczny',
                    message_text=msg_content,
                    sender=sender,
                    recipient=superphraseologist,
                    lemma=binded_lemma,
                    private=False,
                    new=True).save()
    
def create_binding_message_content(main_entry, binded_entry, frame):
    msg_content = u'Do hasła %s (%s) przypisano nowy schemat frazeologiczny %s pochodzący z hasła %s (%s).' % (binded_entry.name, 
                                                                                                               binded_entry.pos.name,
                                                                                                               frame.text_rep,
                                                                                                               main_entry.name,
                                                                                                               main_entry.pos.name)
    return msg_content

@ajax(method='get', encode_result=True)         
def entry_lookup(request, term):
    results = []
    term = unicode(term)
    if len(term) > 0:
        model_results = Entry.objects.exclude(pos__tag='unk').filter(name__startswith=term).order_by('name')
        results = [ (u'%s %s' % (x.name, x.pos.name), x.id) for x in model_results ]
    return {'result': results}

######################### LEMMA NOTES ###################
@ajax(method='post')
def remove_lemma_note(request, message_id):
    try:
        message_obj = Message.objects.get(id=message_id)
    except Message.DoesNotExist:
        raise AjaxError('already removed')
    if(message_obj.sender != request.user or not message_obj.private):
        raise AjaxError('can not remove')
    message_obj.delete();
    return {}

############### CZASOWNIKI PODOBNE ###################
@ajax(method='post')
def similar_lemmas_reset(request):
  request.session['similar_lemmas'] = ''
  request.session['related_lemmas'] = ''
  return {}

@ajax(method='get')
def preview_select(request, isPreview):
    reload = True
    if('lemma_preview' in request.session and 
       request.session['lemma_preview'] == isPreview):
        reload = False   
    request.session['lemma_preview'] = isPreview
    return {'reload': reload}

def getLemmaCompatibility(lemma, comp_lemma):
  intersection = 0
  for old_frame in lemma.old_frames.all():
    old_frames = comp_lemma.old_frames.filter(old_frame_value=old_frame.old_frame_value,
                                              property=old_frame.property,
                                              reflex=old_frame.reflex)
    if old_frames.count() > 0:
      intersection = intersection + 1
  sum = lemma.old_frames.count() + comp_lemma.old_frames.count() - intersection
  intersection = float(intersection)
  # wspolczynnik podobienstwa Jaccard'a
  return (intersection/sum)*100 

@ajax(method='post')
def similar_lemmas_old_form_submit(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  try:
    lemma = Lemma.objects.get(id=form_dict['lemma_id'])
  except Lemma.DoesNotExist:
    raise AjaxError('main lemma not selected')
  if not form_dict['compatibility']:
    raise AjaxError('compatibility not selected')
  if not form_dict['compatibility'].isdigit():
    raise AjaxError('compatibility not digit')
  if int(form_dict['compatibility']) < 1 or int(form_dict['compatibility']) > 100:
    raise AjaxError('wrong compatibility range')
  lemma = Lemma.objects.get(id=form_dict['lemma_id'])
  similar_lemmas = []
  for frame in lemma.old_frames.all():
    for relLemma in frame.lemmas.filter(old=False).all():
    # sprawdza czy uzytkownik moze ogladac hasla w danym slowniku, jesli nie to nie ma co liczyc
      try:
        relLemma.vocabulary.viewers.get(username=request.user.username)
        view_lemma = True
      except:
        view_lemma = False
      if (not relLemma.old and view_lemma):
        compatibility = getLemmaCompatibility(lemma, relLemma)
        if compatibility >= int(form_dict['compatibility']):
          similar_lemmas.append(relLemma)
  if len(similar_lemmas) > 0:
    q_list = []
    for similar_lemma in similar_lemmas:
      q_list.append(Q(id=similar_lemma.id))
    similar_lemmas_query = Lemma.objects.filter(reduce(operator.or_, q_list)) 
    request.session['similar_lemmas'] = similar_lemmas_query.all()
  else:
    raise AjaxError('similar lemmas not found')
  return {}

@ajax(method='post')
def similar_lemmas_show_synonyms(request, lemma_id):
    similar_lemmas = []
    try:
        lemma = Lemma.objects.get(id=lemma_id)
    except Lemma.DoesNotExist:
        raise AjaxError('main lemma not selected')
    q_synonyms = [Q(entry=lemma.entry)]
    try:
        entry_obj = Entry.objects.get(name=lemma.entry)
        for synonym in entry_obj.synonyms.all():
            q_synonyms.append(Q(entry=synonym.name))
        for synonym in entry_obj.rel_synonyms.all():
            q_synonyms.append(Q(entry=synonym.name))
        similar_lemmas = Lemma.objects.filter(old=False).filter(reduce(operator.or_, q_synonyms)).distinct().all()
    except Entry.DoesNotExist:
        pass
    if len(similar_lemmas) > 0:
        request.session['similar_lemmas'] = similar_lemmas
    else:
        raise AjaxError('similar lemmas not found')
    return {}

@ajax(method='post')
def related_lemmas_show(request, lemma_id):
    related_lemmas = []
    try:
        lemma = Lemma.objects.get(id=lemma_id)
    except Lemma.DoesNotExist:
        raise AjaxError('main lemma not selected')
    q_related_lemmas = []
    try:
        entry_obj = Entry.objects.get(name=lemma.entry)
        if entry_obj.rel_entries.exists():
            for related_lemma in entry_obj.rel_entries.all():
                q_related_lemmas.append(Q(entry=related_lemma.name))
            related_lemmas = Lemma.objects.filter(old=False).filter(reduce(operator.or_, q_related_lemmas)).distinct().all()
        else:
            related_lemmas = Lemma.objects.none()
    except Entry.DoesNotExist:
        pass
    if len(related_lemmas) > 0:
        request.session['similar_lemmas'] = related_lemmas
    else:
        raise AjaxError('related lemmas not found')
    return {}

def getLemmaCompatibilityNewFr(lemma, comp_lemma):
  intersection = 0
  for frame in lemma.frames.all():
    for comp_frame in comp_lemma.frames.all():
      if (frame.text_rep == comp_frame.text_rep):
        intersection = intersection + 1
        break
  sum = len(lemma.frames.all()) + len(comp_lemma.frames.all()) - intersection
  intersection = float(intersection)
  sum = float(sum)
  # wspolczynnik podobienstwa Jaccard'a
  return (intersection/sum)*100

@ajax(method='post')
def similar_lemmas_new_form_submit(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  try:
    lemma = Lemma.objects.get(id=form_dict['lemma_id'])
  except Lemma.DoesNotExist:
    raise AjaxError('main lemma not selected')
  if not form_dict['compatibility']:
    raise AjaxError('compatibility not selected')
  if not form_dict['compatibility'].isdigit():
    raise AjaxError('compatibility not digit')
  if int(form_dict['compatibility']) < 1 or int(form_dict['compatibility']) > 100:
    raise AjaxError('wrong compatibility range')
  if not form_dict['status']:
    raise AjaxError('status not selected')
  lemma = Lemma.objects.get(id=form_dict['lemma_id'])
  status_priority = Lemma_Status.objects.get(pk=form_dict['status']).priority
  similar_lemmas = []
  for frame in lemma.frames.all():
    for relLemma in frame.lemmas.all():
    # sprawdza czy uzytkownik moze ogladac hasla w danym slowniku, jesli nie to nie ma co liczyc
      try:
        relLemma.vocabulary.viewers.get(username=request.user.username)
        view_lemma = True
      except:
        view_lemma = False
      if(relLemma.status.priority >= status_priority and not relLemma.old 
         and view_lemma):
        compatibility = getLemmaCompatibilityNewFr(lemma, relLemma)
        if compatibility >= int(form_dict['compatibility']):
          similar_lemmas.append(relLemma)
  if len(similar_lemmas) > 0:
    q_list = []
    for similar_lemma in similar_lemmas:
      q_list.append(Q(id=similar_lemma.id))
    similar_lemmas_query = Lemma.objects.filter(reduce(operator.or_, q_list)) 
    request.session['similar_lemmas'] = similar_lemmas_query.all()
  else:
    raise AjaxError('similar lemmas not found')  
  return {}

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

@ajax(method='post')
def pos_cat_form_submit(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  position = json_decode(form_dict['position_str'])
  pos_cat_str_tab = [] 
  if form_dict['category']:
    category_obj = PositionCategory.objects.get(pk=form_dict['category'])
    pos_cat_str_tab.append(category_obj.category)
  for control in form_dict['control']:
    control_obj = PositionCategory.objects.get(pk=control)
    pos_cat_str_tab.append(control_obj.category)
  position['categories'] = pos_cat_str_tab
  pos_obj = jsPosToObj(position)
  return {'id' : pos_obj.id,
          'text_rep': pos_obj.text_rep,
          'categories': pos_cat_str_tab}

def skladnica_examples_to_js(frame, example):
    """
    Creates client side compatible nkjp_example from selected frame proposition and
    nkjp_example
    """
    arguments_ids = []
    for pos in frame.positions.all():
        try:
            pos_cat = pos.categories.get(control=False)
        except PositionCategory.DoesNotExist:
            pos_cat = None
        match_count = example.skladnica_frame.arguments.filter(possible_args__argument__text_rep=pos.arguments.all()[0].text_rep,
                                                               possible_args__position_category=pos_cat).count()
        if match_count > 0:
            arguments_ids.append('frame_%s_pos_%s_arg_%s_' % 
                                 (str(frame.id), str(pos.id), str(pos.arguments.all()[0].id)))
        elif pos.arguments.all()[0].text_rep == 'refl' and example.skladnica_frame.reflex:
            arguments_ids.append('frame_%s_pos_%s_arg_%s_' % 
                                 (str(frame.id), str(pos.id), str(pos.arguments.all()[0].id)))                 
    return {'example_id'    : 0,
            'frame_id'      : 'frame_%s_' % str(frame.id),
            'arguments_ids' : arguments_ids,
            'sentence'      : example.sentence,
            'source'        : example.source.source,
            'opinion'       : example.opinion.opinion,
            'comment'       : example.comment} 

@ajax(method='post')
def frame_form_submit(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  lemma_obj = Lemma.objects.get(id=form_dict['lemma_id'])
  if (not form_dict['opinion'] or not form_dict['aspect'] or not form_dict['reflex'] or
      not form_dict['negativity'] or not form_dict['predicativity'] or
      ('propose_phraseology' in form_dict and not form_dict['propose_phraseology'])):
    raise AjaxError('empty fields error')
  phraseologic_frame = False
 # tworzenie i dodawanie nowo stworzonych ramek, pozycji, argumentow
  frame_characteristic_objs = []
  # aspekt
  aspect_char_obj = get_frame_char_by_type_and_value_pk(u'ASPEKT', form_dict['aspect'])
  frame_characteristic_objs.append(aspect_char_obj)
  # zwrotnosc
  reflex_char_obj = get_frame_char_by_type_and_value_pk(u'ZWROTNOŚĆ', form_dict['reflex'])
  frame_characteristic_objs.append(reflex_char_obj)
  # negatywnosc
  neg_char_obj = get_frame_char_by_type_and_value_pk(u'NEGATYWNOŚĆ', form_dict['negativity'])
  frame_characteristic_objs.append(neg_char_obj)
  # predykatywnosc
  pred_char_obj = get_frame_char_by_type_and_value_pk(u'PREDYKATYWNOŚĆ', form_dict['predicativity'])
  frame_characteristic_objs.append(pred_char_obj)

  frame_characteristic_objs = sortFrameChars(frame_characteristic_objs)
  opinion = Frame_Opinion_Value.objects.get(pk=form_dict['opinion'])
  frame_char_str_tab = [frame_char.value.value 
                        for frame_char in frame_characteristic_objs]
  if form_dict['frame_realization']:
      selected_frame = Frame.objects.get(id=form_dict['frame_realization'])
       # konwertowanie przykladow na zrozumiale przez java sript
      examples = []
      for example_id in form_dict['selected_examples']:
          examples.append(skladnica_examples_to_js(selected_frame, NKJP_Example.objects.get(id=example_id)))

      frame_id = selected_frame.id
      text_rep = selected_frame.text_rep
      json_frame = json_encode(frameObjToSerializableDict(lemma_obj, selected_frame))
      json_examples = json_encode(examples)
# wybrano jedną z podpowiadanych ramek frazeologicznych
  elif 'propose_phraseology' in form_dict and form_dict['propose_phraseology']:
      selected_frame = Frame.objects.get(id=form_dict['propose_phraseology'])
      frame_id = selected_frame.id
      text_rep = selected_frame.text_rep
      json_frame = json_encode(frameObjToSerializableDict(lemma_obj, selected_frame))
      json_examples = json_encode([])
      phraseologic_frame = True
  elif form_dict['base_frame']:
      selected_frame = Frame.objects.get(id=form_dict['base_frame'])
      frame_id = selected_frame.id
      text_rep = selected_frame.text_rep
      json_frame = json_encode(frameObjToSerializableDict(lemma_obj, selected_frame))
      json_examples = json_encode([])
  elif form_dict['frame_str']:
      frame = json_decode(form_dict['frame_str'])
      positions_objs = []
      for position in frame['positions']:
        pos_obj = jsPosToObj(position)
        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)
        
      text_rep = u'%s:%s' % (':'.join(frame_char_str_tab), 
                             '+'.join(sort_pos_str_tab))
        
      try:
        new_frame_obj = Frame.objects.get(text_rep=text_rep)
      except Frame.DoesNotExist:
        new_frame_obj = Frame(text_rep=text_rep)
        new_frame_obj.save()
        for pos_obj in positions_objs:
          new_frame_obj.positions.add(pos_obj)
        for frame_char in frame_characteristic_objs:
          new_frame_obj.characteristics.add(frame_char)
        if new_frame_obj.has_phraseologic_arguments():
            new_frame_obj.phraseologic = True
            new_frame_obj.save()
    
      serialized_frame = frameObjToSerializableDict(lemma_obj, new_frame_obj)  
      json_frame = json_encode(serialized_frame)
      frame_id = new_frame_obj.id
      text_rep = new_frame_obj.text_rep
      json_examples = json_encode([])
  else:
      raise AjaxError('data error')

  return {'id' : frame_id,
          'text_rep': text_rep, 
          'opinion': opinion.value,
          'characteristics': frame_char_str_tab,
          'frame': json_frame,
          'examples': json_examples,
          'phraseologic': phraseologic_frame} 

@ajax(method='post')
def get_skladnica_example(request, skl_frame_id):  
    try:
        example_obj = Old_Frame.objects.get(id=skl_frame_id).example
        example = {'example_id'    : '',
                   'frame_id'      : '',
                   'arguments_ids' : [],
                   'sentence'      : example_obj.sentence,
                   'source'        : example_obj.source.id,
                   'opinion'       : example_obj.opinion.id,
                   'comment'       : example_obj.comment}
    except ValueError:
        example = ''
    return {'example': json_encode(example)}

@ajax(method='post')
def get_xcp_example(requesr, example_id):
    try:
        example_obj = XcpExample.objects.get(id=example_id).example
        example = {'example_id'    : '',
                   'frame_id'      : '',
                   'arguments_ids' : [],
                   'sentence'      : example_obj.sentence,
                   'source'        : example_obj.source.id,
                   'opinion'       : example_obj.opinion.id,
                   'comment'       : example_obj.comment}
    except ValueError:
        example = ''
    return {'example': json_encode(example)}

@ajax(method='post')
def get_frame_chars(request, frame_id):  
    reflex_id = None
    if frame_id:
        reflex_id = Frame.objects.get(id=frame_id).characteristics.get(type=u'ZWROTNOŚĆ').value.id
        negativity_id = Frame.objects.get(id=frame_id).characteristics.get(type=u'NEGATYWNOŚĆ').value.id
        pred_id = Frame.objects.get(id=frame_id).characteristics.get(type=u'PREDYKATYWNOŚĆ').value.id
        aspect_id = Frame.objects.get(id=frame_id).characteristics.get(type=u'ASPEKT').value.id
    return {'reflex_id': reflex_id,
            'negativity_id': negativity_id,
            'predicativity_id': pred_id,
            'aspect_id': aspect_id}

@render('xcp_example_propositions.html')
@ajax(method='get', encode_result=False)
def xcp_example_propositions(request, frame, argument_ids, lemma_id):
    propositions = []
    lemma_obj = Lemma.objects.get(id=lemma_id)
    entry = lemma_obj.entry_obj
    # TODO: zlikwidowac zaslepke na przyslowki
    if entry.pos.tag != 'adv':
        if argument_ids:
            q_args_ls = []
            xcp_examples = entry.xcp_examples
            for arg_id in argument_ids:
                arg_found = False
                arg_id_ls = arg_id.split('_')
                for pos in frame['positions']:
                    if pos['id'] == int(arg_id_ls[3]):
                        for arg in pos['arguments']:
                            if arg['id'] == int(arg_id_ls[5]):
                                q_args_ls.append(Q(text_rep=arg['text_rep']))
                                arg_found = True
                                break
                        if arg_found:
                            break
            args = Argument.objects.filter(reduce(operator.or_, q_args_ls))
            for xcp_example in xcp_examples.all():
                if args.filter(text_rep__regex=xcp_example.arg_regex).exists():
                    propositions.append(xcp_example)
    if len(propositions) == 0:
        propositions = entry.xcp_examples.all()
    return {'propositions': propositions}

@render('skladnica_example_propositions.html') # harcody tu sa do obmyslenia pozniejszego
@ajax(method='get', encode_result=False)
def skladnica_example_propositions(request, frame, argument_ids, lemma_id):
    q_args_ls = []
    pos_ids = []
    skladnica_frames = []
    if argument_ids:
        reflex = False
        if u'się' in frame['characteristics']:
            reflex = True
        for arg_id in argument_ids:
            arg_found = False
            arg_id_ls = arg_id.split('_')
            # sprawdz czy nie oznaczono dwoch przykladow w jednej pozycji, jesli tak, nie pokazuj proponowanych przykladow
            if int(arg_id_ls[3]) in pos_ids:
                return {'propositions': []}
            else:
                pos_ids.append(int(arg_id_ls[3]))
            for pos in frame['positions']:
                if pos['id'] == int(arg_id_ls[3]):
                    for arg in pos['arguments']:
                        if arg['id'] == int(arg_id_ls[5]):
                            pos_cat = None
                            for cat in pos['categories']:
                                try:
                                    pos_cat = PositionCategory.objects.get(category=cat, control=False)
                                    break
                                except PositionCategory.DoesNotExist:
                                    continue
                            if arg['text_rep'] == 'refl':
                                reflex = True
                            else:
                                q_args_ls.append(Q(arguments__possible_args__argument__text_rep=arg['text_rep'],
                                                   arguments__possible_args__position_category=pos_cat))
                            arg_found = True
                            break
                    if arg_found:
                        break
        skladnica_frames = Lemma.objects.get(old=False, 
                                             id=lemma_id).skladnica_frames.filter(reflex=reflex)
        if q_args_ls:
            for q in q_args_ls:
                skladnica_frames = skladnica_frames.filter(q) 
            skladnica_frames = skladnica_frames.all()
    return {'propositions': skladnica_frames}

@ajax(method='post')
def nkjp_example_form_submit(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  if not (form_dict['sentence'].strip() and form_dict['source'] and form_dict['opinion']):
    raise AjaxError('required fields not selected')
  elif(NKJP_Source.objects.get(pk=form_dict['source']).comment_required and not 
       form_dict['comment'].strip()):
    raise AjaxError('comment required')
  source_str = NKJP_Source.objects.get(pk=form_dict['source']).source
  opinion_str = NKJP_Opinion.objects.get(pk=form_dict['opinion']).opinion   
  return {'sentence' : form_dict['sentence'],
          'source': source_str,
          'opinion': opinion_str,
          'comment': form_dict['comment']}
  
@ajax(method='post')
def semantic_example_form_submit(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  if not (form_dict['sentence'].strip() and form_dict['source'] and form_dict['opinion']):
    raise AjaxError('required fields not selected')
  elif(NKJP_Source.objects.get(pk=form_dict['source']).comment_required and not 
       form_dict['comment'].strip()):
    raise AjaxError('comment required')
  lemma = Lemma.objects.get(id=form_dict['lemma'])
  if lemma.old:
      raise AjaxError('old lemma')
  new_example = add_example(lemma, form_dict)  
  return {'id' : new_example.id,
          'source': new_example.source.source,
          'opinion': new_example.opinion.opinion,
          'comment': new_example.comment,
          'sentence': new_example.sentence}
  
def add_example(lemma, example_dict):
    frame_obj = Frame.objects.get(id=example_dict['frame'])
    argument_selections = []
    for arg_selection in json_decode(example_dict['arg_selections']):
        argument_objs = []
        position_obj = Position.objects.get(id=arg_selection['position']['id'])
        arg_sel_query = NKJP_ArgSelection.objects.filter(position=position_obj)
        for argument in arg_selection['arguments']:
            arg_obj = Argument.objects.get(id=argument['id'])
            argument_objs.append(arg_obj)
            if arg_sel_query.exists():
                arg_sel_query = arg_sel_query.filter(arguments=arg_obj)
        arg_sel_obj = None
        if arg_sel_query.exists():
            for arg_sel in arg_sel_query.all():
                if arg_sel.arguments.count() == len(argument_objs):
                    arg_sel_obj = arg_sel
                    break
        if not arg_sel_obj:
            arg_sel_obj = NKJP_ArgSelection(position=position_obj)
            arg_sel_obj.save()
            for arg_obj in argument_objs:
                arg_sel_obj.arguments.add(arg_obj)
        argument_selections.append(arg_sel_obj)
      
    source_obj = NKJP_Source.objects.get(pk=example_dict['source'])
    opinion_obj = NKJP_Opinion.objects.get(pk=example_dict['opinion'])
    
    # sprawdzanie czy dany obiekt klasy NKJP_Example istnieje
    example_sel_query = NKJP_Example.objects.filter(frame=frame_obj, 
                                                         sentence=example_dict['sentence'], 
                                                         source=source_obj,
                                                         comment=example_dict['comment'], 
                                                         opinion=opinion_obj,
                                                         lemmas__entry_obj=lemma.entry_obj)
    
    for argument_sel in argument_selections:
        if example_sel_query.exists():
            example_sel_query = example_sel_query.filter(arguments=argument_sel)
        else:
            break
    
    example_obj = None
    for example in example_sel_query.all():
        if example.arguments.count() == len(argument_selections):
            example_obj = example
            example_obj.semantic = True
            example_obj.save()
            break
    if not example_obj:
        example_obj = NKJP_Example(frame=frame_obj, sentence=example_dict['sentence'], source=source_obj,
                                        comment=example_dict['comment'], opinion=opinion_obj,
                                        approved=not source_obj.confirmation_required,
                                        semantic=True)
        example_obj.save()
        for argument_selection in argument_selections:
            example_obj.arguments.add(argument_selection) 
    
    lemma.nkjp_examples.add(example_obj)
    return example_obj

@ajax(method='post')
def remove_example_from_lemma(request, lemma_id, example_id):
    lemma = Lemma.objects.get(id=lemma_id)
    if lemma.old:
        raise AjaxError('old lemma')
    example = lemma.nkjp_examples.get(id=example_id)
    lemma.nkjp_examples.remove(example)
    return {}

@ajax(method='post')
def save_new_frames(request, data, id, examples, lemma_examples):
  if not request.user.is_authenticated():
      raise AjaxError('user logged out')
    
  try:
    old_object = Lemma.objects.get(id=id, old=False)
  except:
    raise AjaxError('old version')
    
  if old_object.locker != None:
    raise AjaxError('concurrent access')
  else:
    old_object.locker = request.user
    old_object.old = True
    old_object.save()
  
  # tworzenie nowej wersji hasla
    new_lemma_ver = Lemma(entry=old_object.entry,
                          entry_obj=old_object.entry_obj,
                          owner=old_object.owner,
                          phraseologist=old_object.phraseologist,
                          semanticist=old_object.semanticist,
                          vocabulary=old_object.vocabulary, 
                          status=old_object.status, 
                          old=True, 
                          locker=request.user, 
                          frequency_1M=old_object.frequency_1M,
                          frequency_300M=old_object.frequency_300M)
    new_lemma_ver.save()  
    
    decoded_examples = json_decode(examples)
    decoded_lemma_examples = json_decode(lemma_examples)
  # tworzenie nowo okreslonych ramek, pozycji, argumentow
    frames = json_decode(data)
  
  # tworzenie zmiany do systemu kontroli zmian
    if(old_object.owner):
      lemma_change = Change(user=request.user, entry=old_object, act_owner=old_object.owner)
      lemma_change.save()
    else:
      lemma_change = Change(user=request.user, entry=old_object)
      lemma_change.save()
  
  # przepisywanie starych wersji dla kontroli zmian i dodanie nowej
    for version in old_object.old_versions.all():
      new_lemma_ver.old_versions.add(version)
    new_lemma_ver.old_versions.add(lemma_change)
    
  # przepisywanie historii zmian statusow
    for status_change in old_object.status_history.all():
      new_lemma_ver.status_history.add(status_change)
  
  # przepisywanie wiadomosci
    for message in old_object.messages.all():
      new_lemma_ver.messages.add(message)
    
  # przepisywanie starych ramek
    for old_frame in old_object.old_frames.all():
      new_lemma_ver.old_frames.add(old_frame)
      
  # przepisywanie ramek skladnicowych
    for skladnica_frame in old_object.skladnica_frames.all():
      new_lemma_ver.skladnica_frames.add(skladnica_frame)
      
  # przepisywanie ramek B
    for B_frame in old_object.B_frames.all():
      new_lemma_ver.B_frames.add(B_frame)
  
  # tworzenie ramek i dolaczanie ich do czasownika
    schemata_conversions = []
    for frame in frames:
      frame_obj = jsFrameToObj(frame, new_lemma_ver.entry)
      # blokuje zapisywanie ramek frazeologicznych bez argumentow frazeologicznych
      if (request.user.has_perm('dictionary.add_phraseologic_frames') and 
          frame['is_phraseologic'] and not frame_obj.has_phraseologic_arguments()):
        continue
    # dodawanie opinii o ramce
      if frame['opinion'] and not new_lemma_ver.frame_opinions.filter(frame=frame_obj).exists():
        frame_opinion_val = Frame_Opinion_Value.objects.get(value=frame['opinion'])
        try:
          frame_opinion_obj = Frame_Opinion.objects.get(frame=frame_obj, 
                                                        value=frame_opinion_val)
        except Frame_Opinion.DoesNotExist:
          frame_opinion_obj = Frame_Opinion(frame=frame_obj, 
                                            value=frame_opinion_val)
          frame_opinion_obj.save()
        new_lemma_ver.frame_opinions.add(frame_opinion_obj)    
      new_lemma_ver.frames.add(frame_obj)
      schemata_conversions.append({'js': frame, 'obj': frame_obj})
    
    # reconnect semantics
    sem_reconnect_operations = get_semantic_operations(new_lemma_ver, schemata_conversions)
    update_connections(new_lemma_ver.id, sem_reconnect_operations, request.user)
    
  # dodawanie przykladow do ramek
    reconnect_examples_operations = disconnect_all_examples_operations(old_object)
    for example in decoded_examples:
      frame_obj = jsFrameToObj(example['frame'], new_lemma_ver.entry)
      # blokuje zapisywanie przykladow z ramek frazeologicznych bez argumentow frazeologicznych
      if (request.user.has_perm('dictionary.add_phraseologic_frames') and 
          example['frame']['is_phraseologic'] and not frame_obj.has_phraseologic_arguments()):
          continue
      
      argument_selections = []
      used_pos_obj_ids = []
      for arg_selection in example['arg_selections']:
        try_pos_obj = jsPosToObj(arg_selection['position'])
        pos_objs = Position.objects.filter(text_rep=try_pos_obj.text_rep)
        all_ids_used = False
        existing_pos_ids = []
        for pos_obj in pos_objs:
          existing_pos_ids.append(pos_obj.id)
        not_used_ids = existing_pos_ids
        for pos in pos_objs.all():
          for pos_id in used_pos_obj_ids:
            if pos_id == pos.id:
              not_used_ids.remove(pos_id)
        if len(not_used_ids) > 0:
          for not_used_id in not_used_ids:
            try:
              position_obj = frame_obj.positions.get(id=not_used_id)#Position.objects.get(id=not_used_ids[0])
              break
            except Position.DoesNotExist:
              pass 
        else:
          position_obj = Position(text_rep=try_pos_obj.text_rep)
          position_obj.save()
          for arg in try_pos_obj.arguments.all():
            position_obj.arguments.add(arg)
          for cat in try_pos_obj.categories.all():
            position_obj.categories.add(cat)
        used_pos_obj_ids.append(position_obj.id)
        
        # sprawdzanie czy dany obiekt klasy NKJP_ArgSelection istnieje
        argument_objs = [] 
        nkjp_arg_sel_query = NKJP_ArgSelection.objects.filter(position=position_obj)
        for argument in arg_selection['arguments']:
          try:
            arg_obj = jsArgToObj(argument)
            if arg_obj not in argument_objs:
                argument_objs.append(arg_obj)
                if len(nkjp_arg_sel_query.all()) > 0: # Q objectem to zalatwic
                  nkjp_arg_sel_query = nkjp_arg_sel_query.filter(arguments=arg_obj)
          except TypeError:
            pass
          
          
        nkjp_arg_sel_obj = None
        if len(nkjp_arg_sel_query.all()) > 0:
          for nkjp_arg_sel in nkjp_arg_sel_query.all():
            if len(nkjp_arg_sel.arguments.all()) == len(argument_objs): # zrobic list(set(argument_objs))
              nkjp_arg_sel_obj = nkjp_arg_sel
              break
        if not nkjp_arg_sel_obj:
          nkjp_arg_sel_obj = NKJP_ArgSelection(position=position_obj)
          nkjp_arg_sel_obj.save()
          for arg_obj in argument_objs:
            nkjp_arg_sel_obj.arguments.add(arg_obj)
    
        argument_selections.append(nkjp_arg_sel_obj)
        
      nkjp_source_obj = NKJP_Source.objects.get(source=example['source'])
      nkjp_opinion_obj = NKJP_Opinion.objects.get(opinion=example['opinion'])
      
      # sprawdzanie czy dany obiekt klasy NKJP_Example istnieje
      nkjp_example_sel_query = NKJP_Example.objects.filter(frame=frame_obj, 
                                                             sentence=example['sentence'], 
                                                             source=nkjp_source_obj,
                                                             comment=example['comment'], 
                                                             opinion=nkjp_opinion_obj,
                                                             lemmas__entry=new_lemma_ver.entry)
      
      for argument_sel in argument_selections:
        if nkjp_example_sel_query.exists():
          nkjp_example_sel_query = nkjp_example_sel_query.filter(arguments=argument_sel)
        else:
          break
      
      nkjp_example_obj = None
      for nkjp_example in nkjp_example_sel_query.all():
          if nkjp_example.arguments.count() == len(argument_selections):
              nkjp_example_obj = nkjp_example
              break
      if not nkjp_example_obj:
          nkjp_example_obj = NKJP_Example(frame=frame_obj, sentence=example['sentence'], source=nkjp_source_obj,
                                        comment=example['comment'], opinion=nkjp_opinion_obj,
                                        approved=not nkjp_source_obj.confirmation_required)
          nkjp_example_obj.save()
          for argument_selection in argument_selections:
            nkjp_example_obj.arguments.add(argument_selection) 
      new_lemma_ver.nkjp_examples.add(nkjp_example_obj)
      if example['lexical_unit'] > 0:
          try:
              reconnect_examples_operations.remove(disconnect_example_operation(example, nkjp_example_obj))
          except ValueError:
              reconnect_examples_operations.append(connect_example_operation(example, nkjp_example_obj))
    reconnect_examples(new_lemma_ver, reconnect_examples_operations)
    
# dodawanie przykladow nkjp do czasownika
    for example in decoded_lemma_examples:
      source_obj = NKJP_Source.objects.get(source=example['source'])
      opinion_obj = NKJP_Opinion.objects.get(opinion=example['opinion'])
      # sprawdzanie czy dany obiekt klasy NKJP_Example istnieje      
      nkjp_example_sel_query = NKJP_Example.objects.filter(frame=None,
                                                           sentence=example['sentence'], 
                                                           source=source_obj,
                                                           comment=example['comment'], 
                                                           opinion=opinion_obj,
                                                           lemmasSelf__entry=new_lemma_ver.entry)
      nkjp_lemma_example_obj = None
      for nkjp_example in nkjp_example_sel_query.all():
        if not nkjp_example.arguments.exists():
          nkjp_lemma_example_obj = nkjp_example
          break
      
      if not nkjp_lemma_example_obj:
        nkjp_lemma_example_obj = NKJP_Example(sentence=example['sentence'], source=source_obj, 
                                              comment=example['comment'], opinion=opinion_obj, 
                                              approved=not source_obj.confirmation_required)
        nkjp_lemma_example_obj.save() 
      new_lemma_ver.lemma_nkjp_examples.add(nkjp_lemma_example_obj)
    
    old_object.locker = None
    old_object.save()
    new_lemma_ver.locker = None
    try:
      new_lemma_ver = Lemma.objects.get(entry=old_object.entry, owner=old_object.owner,
                            vocabulary=old_object.vocabulary, status=old_object.status, 
                            old=False)
      raise AjaxError('concurrent access')
    except:
      new_lemma_ver.old = False
      new_lemma_ver.save()
      
  return {'id'           : new_lemma_ver.id,
          'entry'        : new_lemma_ver.entry,
          'error_message': '',
          'frames'       : ''}
    
############## WALIDACJA #####################

@ajax(method='post')
def validate_new_frames(request, data, id, examples, lemma_examples, 
                          status_id, selected_frame_id):
  old_object = Lemma.objects.get(id=id)
  
  status_need_validation = False
  status_need_examples_check = False
  status_need_semantic_check = False
  try:
      status_obj = Lemma_Status.objects.get(id=status_id)
      status_need_validation = status_obj.validate
      status_need_examples_check = status_obj.check_examples
      status_need_semantic_check = status_obj.check_semantics
  except Lemma_Status.DoesNotExist:
      status_obj = None

  frames = json_decode(data)
  
  serialized_frames = []
  error = False
  if status_need_examples_check and not status_need_validation:
      serialized_frames, error = validate_examples_and_mark_errors(old_object, status_obj, selected_frame_id)
  elif status_need_validation or not status_obj:
      serialized_frames, error = validate_schemas_and_mark_errors(old_object, status_obj, selected_frame_id)
  elif status_need_semantic_check:
      serialized_frames, error = validate_schemata_for_semantics_and_mark_errors(old_object, status_obj, selected_frame_id)
  
  if error:
    return {'id'             : '',
            'entry'          : '',
            'error_message'  : u'Hasło/schemat zawiera błędy, przejdź do zakładki ze schematami walencyjnymi, aby je zobaczyć, jeśli nie są widoczne, sprawdź ustawienia filtrów i powtórz walidację.',
            'confirm_message': False,
            'frames'         : serialized_frames} 
    
  if(not selected_frame_id and (status_need_validation or not status_obj)):
      message_content = ''
      aspect_rel_lemmas = get_aspect_rel_lemmas(old_object)  
      missing_frames = get_all_test_missing_frames(frames, aspect_rel_lemmas) 
      missmatched_B_frames = validate_B_frames(old_object)
      wrong_aspect_frames = get_wrong_aspect_frames(old_object, old_object.frames.order_by('text_rep'))
      deriv_miss_frames_msg = get_deriv_miss_frames_message(old_object)
      if old_object.entry_obj.pos.tag == 'verb':
          message_content += get_missing_aspects_msg(old_object)
      if wrong_aspect_frames:
          message_content += u'Podane poniżej schematy mają aspekt niezgodny z Morfeuszem, zaleca się ich dodatkowe sprawdzenie:\n'
          for frame in wrong_aspect_frames:
              message_content += u'\t- [%d] %s\n' % (frame.id, frame.text_rep)
          message_content += '\n'
      if missing_frames:
          message_content += u'Edytowane hasło nie posiada następujących schematów z powiązanych aspektowo lematów:\n'
          for miss_frame in missing_frames:
              message_content += u'  %s\n' % miss_frame['lemma']
              for frame in miss_frame['frames']:
                  message_content += u'\t- %s\n' % (frame['frame'].text_rep)
          message_content += '\n'
      phraseology_bindings_message = validate_phraseology_binded_frames(old_object)
      if phraseology_bindings_message:
          message_content += phraseology_bindings_message
      if len(missmatched_B_frames) > 0:
          message_content += u'Sugerowane jest dodanie do edytowanego hasła schematów postaci:\n'
          for miss_frame in missmatched_B_frames:
              message_content += u'\t- %s\n' % (miss_frame.text_rep)
          message_content += '\n'
      message_content += deriv_miss_frames_msg
      message_content += validate_same_positions_schemata(old_object)
      frames_to_merge = find_similar_frames(old_object.frames.all())
      if len(frames_to_merge) > 0:
          message_content += u'Sugerowane jest połączenie poniższych schematów, zawierają one często koordynujące się typy fraz:\n'
          for comb in frames_to_merge:
              message_content += u'\t- [%d] %s i \n\t  [%d] %s x %d\n' % (comb['frames'][0].id, comb['frames'][0].text_rep, 
                                                                          comb['frames'][1].id, comb['frames'][1].text_rep,
                                                                          comb['occurrences'])
          message_content += '\n'
      if message_content: 
          if status_need_validation:           
              message_content += u'Czy jesteś pewien, że chcesz zmienić status hasła?'
          else:
              message_content = message_content.strip()
          return {'id'           : '',
                  'entry'        : '',
                  'error_message': message_content,
                  'confirm_message': status_need_validation,            
                  'frames'       : serialized_frames}
      
  return {'id'             : '',
          'entry'          : '',
          'error_message'  : '',
          'confirm_message': False,
          'frames'         : ''}

########################## END WALIDACJA ###########################################

class LemmaGrid(JqGridAjax):
  model = Lemma
  search_field = 'entry'
  field_translation = {
    'id': 'id',
    'entry': 'entry',
    'owner': 'owner__username',
    'phraseologist': 'phraseologist__username',
    'semanticist': 'semanticist__username',
    'vocabulary': 'vocabulary__name',
    'status': 'status__status'
  }
  
  @staticmethod
  def sort_field_special_case(rule):
    if rule['field'] == 'entry' and rule['a_tergo']:
      return 'rev'
    else:
      return rule['field']

  @staticmethod
  def sort_queryset_special_case(queryset, rule):
    if rule['field'] == 'entry' and rule['a_tergo']:
      return queryset.extra(select={'rev': "reverse(haslo)"})
    else:
      return queryset

  @staticmethod
  def filter_special_case(filter, lookup, negated, queryset):
    return True

  @staticmethod
  def get_queryset(vocabularies):
    return True

  @staticmethod
  def apply_mask(lemmas, mask):
    matching_lemmas = lemmas.filter(entry__istartswith=mask)
    return matching_lemmas

  @staticmethod
  def filter_value_special_case(queryset, rule, from_value, greater):
    if rule['field'] == 'entry' and rule['a_tergo']:
      if greater:
        comp = '>='
      else:
        comp = '<='
      queryset = queryset.extra(where=["reverse(haslo) " + comp + " %s"],
                                params=[reverse(from_value)])
      return True, queryset
    else:
      return False, queryset

  @staticmethod
  def get_field_special_case(field, lexeme):
    if field == 'part_of_speech':
      return True, lexeme.part_of_speech.symbol
    else:
      return False, None

  @staticmethod
  def response_row(lemma):
    owner_name = ''
    phraseologist_name = ''
    semanticist_name = ''
    if lemma.owner:
        owner_name = lemma.owner.username
    if lemma.phraseologist:
        phraseologist_name = lemma.phraseologist.username
    if lemma.semanticist:
        semanticist_name = lemma.semanticist.username
    return {
      'id' : lemma.id,
      'entry' : lemma.entry,
      'owner' : owner_name,
      'phraseologist' : phraseologist_name,
      'semanticist' : semanticist_name,
      'vocabulary' : lemma.vocabulary.name,
      'status' : lemma.status.status,}

  @classmethod
  def get_location(self, filtering_mode, sort_rules, filters, mask, *args):
    selected_pk, index, count = self.get_pk(
      mask, filters, sort_rules, filtering_mode, *args)
    return {
      'rowIndex': index,
      'selected_id': selected_pk,
      'records': count,
    }
    
def order_sort_rules(sort_rules):
  cleared_sort_rules = []
  if(sort_rules['id']['priority']):
    cleared_sort_rules.append({'name' : 'id',
                               'rules': sort_rules['id']})
  if(sort_rules['entry']['priority']):
    cleared_sort_rules.append({'name' : 'entry',
                               'rules': sort_rules['entry']})
  if(sort_rules['owner']['priority']):
    cleared_sort_rules.append({'name' : 'owner',
                               'rules': sort_rules['owner']})
  if(sort_rules['phraseologist']['priority']):
    cleared_sort_rules.append({'name' : 'phraseologist',
                               'rules': sort_rules['phraseologist']})
  if(sort_rules['semanticist']['priority']):
    cleared_sort_rules.append({'name' : 'semanticist',
                               'rules': sort_rules['semanticist']})
  if(sort_rules['vocabulary']['priority']):
    cleared_sort_rules.append({'name' : 'vocabulary',
                               'rules': sort_rules['vocabulary']})
  if(sort_rules['status']['priority']):
    cleared_sort_rules.append({'name' : 'status',
                               'rules': sort_rules['status']})
  ordered_sort_rules = []
  while not len(cleared_sort_rules) == 0:
    highest_prior_rule_idx = 0
    for i in range(len(cleared_sort_rules)):
      if cleared_sort_rules[i]['rules']['priority'] < cleared_sort_rules[highest_prior_rule_idx]['rules']['priority']:
        highest_prior_rule_idx = i
    ordered_sort_rules.append(cleared_sort_rules.pop(highest_prior_rule_idx))
  return ordered_sort_rules
    
def prepare_sort_rules(sort_rules):
  ordered_sort_rules = order_sort_rules(sort_rules)
  prepared_sort_rules = []
  for rule in ordered_sort_rules:
    if rule['name'] == u'owner' or rule['name'] == u'phraseologist' or rule['name'] == u'semanticist':
        rule['name'] = rule['name'] + '__username'
    if rule['rules']['sort_order'] == u'desc':
        prepared_sort_rules.append(u'-'+rule['name'])
    else:
        prepared_sort_rules.append(rule['name'])
  return prepared_sort_rules

def get_lemma_query(prepared_sort_rules, filter_rules, lemma_query, user):
  lemmas = Lemma.objects.none()
  if user.is_authenticated():
      visible_vocabs = user.visible_vocabularies.all()
      visible_statuses = Lemma_Status.objects.all()
  else:
      visible_vocabs = get_anon_profile().visible_vocabularies().all()
      visible_statuses = get_anon_profile().visible_statuses.all()
  q_vocab_list = []
  for vocab in visible_vocabs:
    q_vocab_list.append(Q(vocabulary=vocab))  
    
  q_status_list = []
  for status in visible_statuses:
    q_status_list.append(Q(status=status))
  
  lemmas = lemma_query.filter(old=False)
  lemmas = lemmas.filter(reduce(operator.or_, q_vocab_list))
  lemmas = lemmas.filter(reduce(operator.or_, q_status_list))
  
  ## filtrowanie
  lemmas = filter_lemmas(lemmas, filter_rules, user)
  
  ## sortowanie
  entrySortDefined = False
  for sort_rule in prepared_sort_rules:
      if sort_rule.endswith('entry'):
        entrySortDefined = True
        break
    
  if not entrySortDefined:
      prepared_sort_rules.append('entry')
      
  if len(prepared_sort_rules) == 1:
      lemmas = lemmas.order_by(prepared_sort_rules[0]) 
  elif len(prepared_sort_rules) == 2:
      lemmas = lemmas.order_by(prepared_sort_rules[0], prepared_sort_rules[1]) 
  elif len(prepared_sort_rules) == 3:
      lemmas = lemmas.order_by(prepared_sort_rules[0], prepared_sort_rules[1],
                               prepared_sort_rules[2]) 
  elif len(prepared_sort_rules) == 4:
      lemmas = lemmas.order_by(prepared_sort_rules[0], prepared_sort_rules[1],
                               prepared_sort_rules[2], prepared_sort_rules[3])
  elif len(prepared_sort_rules) == 5:
      lemmas = lemmas.order_by(prepared_sort_rules[0], prepared_sort_rules[1],
                               prepared_sort_rules[2], prepared_sort_rules[3],
                               prepared_sort_rules[4])
  elif len(prepared_sort_rules) == 6:
      lemmas = lemmas.order_by(prepared_sort_rules[0], prepared_sort_rules[1],
                               prepared_sort_rules[2], prepared_sort_rules[3],
                               prepared_sort_rules[4], prepared_sort_rules[5])
  return lemmas

@ajax(method='get')
def get_lemmas(request, page, rows, sort_rules=None, filters=None, 
                mask='', target_page=0, totalrows=0):
  similar_lemmas = ''
  if request.session.has_key('lemma_preview') and request.session['lemma_preview']:
      if not request.session.has_key('sort_rules_lemma_preview'):
          request.session['sort_rules_lemma_preview'] = default_sort_rules()
      sort_rules = request.session['sort_rules_lemma_preview']
      if not request.session.has_key('filter_rules_lemma_preview'):
          request.session['filter_rules_lemma_preview'] = default_filter_rules()
      filter_rules = request.session['filter_rules_lemma_preview']
      similar_lemmas = request.session['similar_lemmas']  
  else:
      if not request.session.has_key('sort_rules'):
          request.session['sort_rules'] = default_sort_rules()
      sort_rules = request.session['sort_rules']
      if not request.session.has_key('filter_rules'):
          request.session['filter_rules'] = default_filter_rules()
      filter_rules = request.session['filter_rules']
  prepared_sort_rules = prepare_sort_rules(sort_rules)

  if not similar_lemmas:
    lemma_query = get_lemma_query(prepared_sort_rules, filter_rules, Lemma.objects, request.user)
  else:
    lemma_query = get_lemma_query(prepared_sort_rules, filter_rules, similar_lemmas, request.user)
  lemmas = list(lemma_query)
  count = lemma_query.count()
  total_pages = math.ceil(count/50)
  page = target_page or page
  limit = totalrows or rows
  total_pages, start, response_rowcount = LemmaGrid.count_pages(count, page, limit)
  lemmas = lemmas[start:start + response_rowcount]
  return LemmaGrid.make_response(lemmas, count, page, total_pages)

# Zapytanie o id oraz indeks pierwszego wiersza przy danym sortowaniu,
# którego hasło rozpoczyna się od mask.
# 'selected_id' == None, jeśli takiego nie ma
@ajax(method='get')
def get_location(request, mask='', id=''):
  similar_lemmas = ''
  if request.session.has_key('lemma_preview') and request.session['lemma_preview']:
    if not request.session.has_key('sort_rules_lemma_preview'):
        request.session['sort_rules_lemma_preview'] = default_sort_rules()
    sort_rules = request.session['sort_rules_lemma_preview']
    if not request.session.has_key('filter_rules_lemma_preview'):
        request.session['filter_rules_lemma_preview'] = default_filter_rules()
    filter_rules = request.session['filter_rules_lemma_preview']
    similar_lemmas = request.session['similar_lemmas']  
  else:
    if not request.session.has_key('sort_rules'):
        request.session['sort_rules'] = default_sort_rules()
    sort_rules = request.session['sort_rules']
    if not request.session.has_key('filter_rules'):
        request.session['filter_rules'] = default_filter_rules()
    filter_rules = request.session['filter_rules']
  prepared_sort_rules = prepare_sort_rules(sort_rules)

  if not similar_lemmas:
    lemma_query = get_lemma_query(prepared_sort_rules, filter_rules, Lemma.objects, request.user)
  else:
    lemma_query = get_lemma_query(prepared_sort_rules, filter_rules, similar_lemmas, request.user)
  
  matching_lemmas = list(lemma_query.filter(entry__istartswith=mask))
  
  lemmas = lemma_query
  lemmas_list = list(lemmas)

# warto to potem zastapic czyms madrzejszym
  if(len(matching_lemmas) == 0): 
    matching_lemmas = lemmas_list

  lemma_nfound = False
  firstMatchingLemma = None
  if id:
    try:
      firstMatchingLemma = lemmas.get(id=id)
    except:
      if len(lemmas.all()) > 0:
        firstMatchingLemma = lemmas.all()[0]
      lemma_nfound = True
  else:
    if len(matching_lemmas) > 0:
      firstMatchingLemma = matching_lemmas[0]
    lemma_nfound = True
    
  if firstMatchingLemma:
    id = firstMatchingLemma.id
    index = lemmas_list.index(firstMatchingLemma) 
  else:
    index = 0
    lemma_nfound = True
  
  return {
      'rowIndex': index,
      'selected_id': id,
      'records': len(lemmas),
      'lemma_nfound': lemma_nfound,}  

@render()
@ajax(method='get', encode_result=False)
def lemma_edit_form(request, id):  
  return id

@render('lemma_note_form.html')
@ajax(method='get', encode_result=False)
def lemma_note_form(request, topic):
  form = MessageForm(hide_private=True, topic=topic)
  return {'add_note_form': form}
  
@ajax(method='get')
def get_actual_lemma_id(request, chosen_id):
    chosen_lemma = Lemma.objects.get(id=chosen_id)
    actual_lemma = Lemma.objects.get(old=False, entry_obj=chosen_lemma.entry_obj)
    return {'actual_id': actual_lemma.id}

@ajax(method='get')
def user_is_authenticated(request):
    return {'authenticated': request.user.is_authenticated()}

######################################################################################
############################### zarzadzanie kontami

@ajax(method='post')
def new_account_form_submit(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  
  username = form_dict['username'].strip()
  email = form_dict['email'].strip()
  
  if (not username or not form_dict['password1'] 
      or not form_dict['password2'] or not form_dict['group'] 
      or not form_dict['email']):
    raise AjaxError('empty fields')

  if not email_re.match(email):
    raise AjaxError('wrong e-mail form')

  if ( form_dict['password1'].strip() != form_dict['password2'].strip()): 
    raise AjaxError('passwords not match')
  
  if not re.match("^[A-Za-z0-9_\-@\.\+]+$", username):
    raise AjaxError('invalid username')

  if not re.match("^[A-Za-z0-9_\-@\.\+]+$", form_dict['password1'].strip()):
    raise AjaxError('invalid password')

  try:
    User.objects.get(username=username)
    raise AjaxError('user exist')
  except User.DoesNotExist:
    pass

  password = form_dict['password1'].strip()
  
  group = Group.objects.get(pk=form_dict['group'])
  new_user = User.objects.create_user(username, email, password)
  UserSettings.objects.create(user=new_user)
  UserStats.objects.create(user=new_user)
  new_user.groups.add(group)
      
  return {}

@render('change_user_fun_form.html')
@ajax(method='get', encode_result=False)
def change_user_fun_form(request, user_id):
  if not user_id:
    change_function_form = ChangeUserFunctionForm()
  else:
    change_function_form = ChangeUserFunctionForm(user_id=user_id)
  return {'user_function_form': change_function_form}

@ajax(method='post')
def change_user_fun_form_submit(request, form_data):
  form_dict = dict((x['name'], x['value']) for x in form_data)
  if (not form_dict['user'] or not form_dict['group']):
    raise AjaxError('empty fields')
  user = User.objects.get(id=form_dict['user'])
  if user.is_superuser:
    raise AjaxError('is superuser')
  user.groups.clear()
  group = Group.objects.get(pk=form_dict['group'])
  user.groups.add(group)  
  return {}

@ajax(method='post')
def delete_user(request, user_id):
  if not user_id:
    raise AjaxError('user not selected')  
  user = User.objects.get(id=user_id)
  if user.is_superuser:
    raise AjaxError('is superuser')
  if user == request.user:
    raise AjaxError('deleting own account')
  user.lemmas.clear()
 # to ma wrocic, zeby usuwalo tylko notatki prywatne
 # notes = user.messages.filter(private=False)
 # for note in notes.all():
 #   user.messages.remove(note) 
  user.delete()        
  return {}

@ajax(method='post')
def deselect_preview_tab(request):  
    request.session['lemma_preview'] = False
    return {}

@ajax(method='get')
def get_schemata(request, lemma_id):
    lemma = Lemma.objects.get(id=lemma_id)  
    schemata = lemma.frames.order_by('text_rep')
    serialized_schemata = [frameObjToSerializableDict(lemma, schema, True) for schema in schemata]
    json_schemata = json_encode(serialized_schemata)
    return {'schemata': json_schemata,
            'can_modify': user_can_modify(lemma, request.user)}
    
@ajax(method='get')
def get_examples(request, lemma_id):
    lemma = Lemma.objects.get(id=lemma_id)  
    examples = lemma.nkjp_examples.all()
    examples_js = nkjpExamplesObjToJs(examples, request.user, lemma)
    json_examples = json_encode(examples_js)
    return {'examples': json_examples,
            'can_modify': user_can_modify(lemma, request.user)}
    
@ajax(method='get')
def get_schemata_and_examples(request, lemma_id):
    lemma = Lemma.objects.get(id=lemma_id)
    
    examples = lemma.nkjp_examples.order_by('source__priority', 
                                            'opinion__priority', 
                                            'sentence')
    examples_js = nkjpExamplesObjToJs(examples, request.user, lemma)
    json_examples = json_encode(examples_js)
    
    lemma_examples = lemma.lemma_nkjp_examples.order_by('source__priority', 
                                                        'opinion__priority', 
                                                        'sentence')
    lemma_examples_js = nkjpLemmaExamplesObjToJs(lemma_examples, request.user, lemma)
    json_lemma_examples = json_encode(lemma_examples_js)
    
    schemata = lemma.frames.order_by('text_rep')
    serialized_schemata = [frameObjToSerializableDict(lemma, schema, True) for schema in schemata]
    json_schemata = json_encode(serialized_schemata)
    
    return {'examples': json_examples,
            'lemma_examples': json_lemma_examples,
            'schemata': json_schemata,
            'can_modify': user_can_modify(lemma, request.user)}
