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

import codecs
import datetime
import os
from tempfile import mkdtemp, mkstemp 

from django.db.models import Count
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

from common.decorators import render, ajax, AjaxError
from dictionary.ajax_argument_form import argument_to_form_values, get_argument_model, \
                                          create_argument_form, all_fields_filled, \
                                          get_argument_from_form, validate_argument_form
from dictionary.ajax_vocabulary_management import create_copyrights_str
from dictionary.forms import ArgRealOpinionForm
from dictionary.models import Argument, ArgRealization, ArgRealOpinion, AttributeParameterModel, \
                              Position, RealizationType, \
                              get_or_create_phrase_type_extension, get_or_create_positions_extension,\
    sort_positions
from settings import PROJECT_PATH

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

@render('show_realizations.html')
@ajax(method='post', encode_result=False)
def show_realizations(request, form_data):  
    form_dict = {}
    error_message = u'Wypełnij wszystkie pola formularza wyboru głównego typu frazy.'
    if form_data: # zaznaczono wartosci
        form_dict = dict((x['name'], x['value']) for x in form_data)    
  # sprawdz czy wypelniono wszystkie pola formularza argumentu glownego
    if not all_fields_filled(form_dict): 
        result = {'error_message': error_message,
                  'realizations': [],
                  'main_arg_text_rep': '',
                  'manage': form_dict['manage']}
    else:
        arg_obj = get_argument_from_form(form_dict['arg_type'], form_dict['subform_values'])
        realizations = arg_obj.realizations.order_by('opinion__priority',
                                                     'type__priority',
                                                     'argument__text_rep')
        result = {'error_message': '',
                  'realizations': realizations,
                  'main_arg_text_rep': arg_obj.text_rep,
                  'manage': form_dict['manage']}
    return result 

@csrf_exempt
@render('arg_realization_form.html')
@ajax(method='post', encode_result=False)
def realization_arg_form(request, form_data, main_argument, real_id):
    form_dict = {}
    attr_subforms_values = []
    if form_data:
        form_dict = dict((x['name'], x['value']) for x in form_data)
    realization_argument = get_arg_from_realization(real_id)
    if realization_argument:
        form_dict = {'arg_id': realization_argument.id}
    arg_model = get_argument_model(form_dict)
    opinion_form = create_opinion_form(real_id)
    if main_argument:
        form_type = 'realization_main_arg'
    else:
        form_type = 'realization_arg'
    if form_dict: # zaznaczono wartosci
    # prezentowanie formularza na podstawie reprezentacji teksowej argumentu
        if form_dict['arg_id']:
            argument = Argument.objects.get(id=form_dict['arg_id'])
            attr_subforms_values = argument_to_form_values(argument) 
        elif form_dict['arg_type']:
            attr_subforms_values = form_dict['subform_values']
    type_form, attr_sheets = create_argument_form(arg_model=arg_model, 
                                                  subforms_values=attr_subforms_values, 
                                                  form_type=form_type) 
    return {'type_form': type_form,
            'attr_sheets': attr_sheets,
            'opinion_form': opinion_form,
            'main_argument': main_argument}
    
def get_arg_from_realization(realization_id):
    argument = None
    if realization_id:
        realization = ArgRealization.objects.get(id=realization_id)
        argument = realization.argument
    return argument

def create_opinion_form(realization_id):
    opinion = None
    if realization_id:
        realization = ArgRealization.objects.get(id=realization_id)
        opinion = realization.opinion
    opinion_form = ArgRealOpinionForm(sel_opinion=opinion)
    return opinion_form

@csrf_exempt
@render('positions_extensions_form.html')
@ajax(method='post', encode_result=False)
def positions_extension_form(request, extension_id=None):
    positions = []
    if extension_id:
        extension = ArgRealization.objects.get(id=extension_id)
        positions = sort_positions(extension.positions.all())
    opinion_form = create_opinion_form(extension_id)
    return {'positions': positions,
            'opinion_form': opinion_form}
    
@ajax(method='post')
def remove_realization(request, realization_id, main_arg_data):
    result = {}   
    # sprawdz czy wypelniono wszystkie pola formularza argumentu glownego
    main_arg_dict = dict((x['name'], x['value']) for x in main_arg_data)
    if not all_fields_filled(main_arg_dict):
        raise AjaxError('empty main argument fields')
    main_arg_obj = get_argument_from_form(main_arg_dict['arg_type'], 
                                          main_arg_dict['subform_values'])
    realization_obj = main_arg_obj.realizations.get(id=realization_id)
    main_arg_obj.realizations.remove(realization_obj)
    if not realization_obj.is_used():
        realization_obj.delete() 
    return result

@ajax(method='post')
def add_arg_realization(request, main_arg_data, realization_data):
    result = {'added': True}   
    # sprawdz czy wypelniono wszystkie pola formularza argumentu glownego
    main_arg_dict = dict((x['name'], x['value']) for x in main_arg_data)
    main_arg_error = validate_argument_form(main_arg_dict)
    if main_arg_error:
        raise AjaxError(u'Główny typ frazy: %s' % main_arg_error)
    
    # sprawdz czy wypelniono wszystkie pola formularza argumentu dodawanego jako realizacja
    realization_dict = dict((x['name'], x['value']) for x in realization_data)
    
    real_arg_error = validate_argument_form(realization_dict)
    
    if real_arg_error:
        raise AjaxError(u'Dodawanie rozwinięć typu frazy: %s' % real_arg_error)
    # nie dodano opinii o realizacji
    if not realization_dict['opinion']:
        raise AjaxError('select opinion')
    # znajdz obiekt argumentu bedacego realizacja
    real_arg_obj = get_argument_from_form(realization_dict['arg_type'], 
                                          realization_dict['subform_values'])
    # znajdz model argumentu bazowego
    main_arg_obj = get_argument_from_form(main_arg_dict['arg_type'], 
                                          main_arg_dict['subform_values'])
    
    opinion = ArgRealOpinion.objects.get(id=realization_dict['opinion'])
    realization_obj, xx = get_or_create_phrase_type_extension(real_arg_obj, opinion)
    real_count = main_arg_obj.realizations.count()
    main_arg_obj.realizations.add(realization_obj) 
    if real_count == main_arg_obj.realizations.count():
        result['added'] = False
    
    return result

@ajax(method='post')
def add_positions_extension(request, main_phrase_type_data, extension_data):
    result = {'added': True}
    # sprawdz czy wypelniono wszystkie pola formularza argumentu glownego
    main_phrase_type_dict = dict((x['name'], x['value']) for x in main_phrase_type_data)
    main_phrase_type_error = validate_argument_form(main_phrase_type_dict)
    if main_phrase_type_error:
        raise AjaxError(u'Główny typ frazy: %s' % main_phrase_type_error)
    
    # sprawdz czy wypelniono wszystkie pola formularza argumentu dodawanego jako realizacja
    extension_dict = dict((x['name'], x['value']) for x in extension_data)
    if not extension_dict['positions']:
        raise AjaxError(u'Dodawanie rozwinięć typu frazy: Nie wybrano żadnej pozycji.')
    
    if not extension_dict['opinion']:
        raise AjaxError('select opinion')
    
    # znajdz model argumentu bazowego
    main_phrase_type_obj = get_argument_from_form(main_phrase_type_dict['arg_type'], 
                                                  main_phrase_type_dict['subform_values'])
    
    opinion = ArgRealOpinion.objects.get(id=extension_dict['opinion'])
    extension_type = RealizationType.objects.get(sym_name='positions')
    positions = [Position.objects.get(id=id) for id in extension_dict['positions']]
    # zle, bo moga istniec realizacje, ktore nie sa nigdzie podpiete
    realization_obj, xx = get_or_create_positions_extension(positions, opinion)
    
    extensions_count = main_phrase_type_obj.realizations.count()
    main_phrase_type_obj.realizations.add(realization_obj) 
    if extensions_count == main_phrase_type_obj.realizations.count():
        result['added'] = False
    
    return result

@ajax(method='post')
def create_realizations(request, form_data):  
    try:
        tmp_folder = mkdtemp()
        os.chdir(tmp_folder)      
        tmpfile, tmpfilename = mkstemp(dir=tmp_folder)
        os.close(tmpfile)
        create_realizations_file(tmpfilename)
        os.rename(tmpfilename, tmpfilename+'.txt')
        file_name = tmpfilename+'.txt'
        return {'file_name': file_name}
    except:
        raise AjaxError('creating realizations file error') 
    
def create_realizations_file(filename):
    try:
        real_file = codecs.open(filename, 'wt', 'utf-8')
        real_file.write(create_copyrights_str(dictionary_file=False,
                                              frame_opinions_pks=[],
                                              lemma_statuses_pks=[], 
                                              poss_pks=[], 
                                              add_frame_opinions=[]))
        write_phrase_types_extensions(real_file)
        real_file.write('\n')
        write_parameters_realizations(real_file)
        real_file.write('\n')   
        write_parameters_equivalents(real_file)                                                
    finally:
        real_file.close() 
        
def write_phrase_types_extensions(extensions_file):
    extensions_file.write('% Phrase types extensions:\n')
    phrase_types = Argument.objects.annotate(extensions_count=Count('realizations'))
    phrase_types_with_extensions = phrase_types.filter(extensions_count__gt=0)
    for phrase_type in phrase_types_with_extensions.order_by('text_rep'):
        extensions_file.write(phrase_type.text_rep + u'-->\n')
        for extension in phrase_type.realizations.order_by('opinion__priority',
                                                           'type__priority',
                                                           'argument__text_rep'):
            extensions_file.write('    %s\t[%s]\n' % (unicode(extension), 
                                                      extension.opinion.value))
        
def write_parameters_realizations(real_file):
    real_file.write('% Attributes subtypes:\n')
    for param_model in AttributeParameterModel.objects.order_by('name').all():
        if param_model.possible_subparams.exists():
            real_file.write(param_model.name + u'-->\n')
            for subparam in param_model.possible_subparams.order_by('opinion__priority', 'name'):
                real_file.write('    %s\t[%s]\n' % (subparam.name, subparam.opinion.value)) 
                
def write_parameters_equivalents(real_file):
    real_file.write('% Attributes equivalents:\n')
    for param_model in AttributeParameterModel.objects.order_by('name').all():
        if param_model.related_param_models.exists():
            real_file.write(param_model.name + u'-->\n')
            for equivalent_model in param_model.related_param_models.order_by('name'):
                real_file.write('    %s\n' % equivalent_model.name) 
    

def download_realizations(request, file_name):  
  fullpath = os.path.join(DEFAULT_SAVE_PATH, file_name)
  response = None
  download_file_name = '%s_%s' % ('phrase_types_expand', datetime.datetime.now().strftime('%Y%m%d'))
  if file_name.endswith('.txt'):
    fullpath = '/' + file_name
    with open(fullpath, "r") as f:
        data = f.read()
    response = HttpResponse(data, mimetype='text/txt')
    response['Content-Disposition'] = 'attachment; filename=%s.txt' % download_file_name
    os.remove(fullpath)
    os.rmdir(os.path.split(fullpath)[0])
  return response
