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

"""Module covering functions used in user statistics views"""

import operator

from django.contrib.auth.models import User
from django.db.models import Count, Sum, Q

from common.decorators import render, ajax
from dictionary.models import Lemma, Lemma_Status
from accounts.models import RealizedLemma, RealizedPhraseology, \
                            RealizedPhraseologyBinding, RealizedSemantics

@render('sel_user_stats.html')
@ajax(method='get', encode_result=False)
def get_user_stats(request, user_name):
  """Function rendering sel_user_stats.html page."""
  if user_name:
    user = User.objects.get(username=user_name)
  else:
    user = request.user
  
  all_owned_lemmas = user.lemmas.filter(old=False)
  all_phraseologic_owned_lemmas = user.phraseologist_lemmas.filter(old=False)
  all_semantic_owned_lemmas = user.semanticist_lemmas.filter(old=False)
  ord_statuses = Lemma_Status.objects.order_by('priority')[1:]
  status_table_dict = []
  all_owned_frames_count = 0
  all_phraseologic_owned_frames_count = 0
  all_semantic_owned_frames_count = 0

  for status in ord_statuses:
    owned_lemmas = all_owned_lemmas.filter(status=status)
    phraseologic_owned_lemmas = all_phraseologic_owned_lemmas.filter(status=status)
    semantic_owned_lemmas = all_semantic_owned_lemmas.filter(status=status)
    owned_frames_count = owned_lemmas.annotate(num_frames=Count('frames')).aggregate(Sum('num_frames'))['num_frames__sum']
    phraseologic_owned_frames_count = phraseologic_owned_lemmas.annotate(num_frames=Count('frames')).aggregate(Sum('num_frames'))['num_frames__sum']
    semantic_owned_frames_count = semantic_owned_lemmas.annotate(num_frames=Count('frames')).aggregate(Sum('num_frames'))['num_frames__sum']
    
    if not owned_frames_count:
        owned_frames_count = 0
    if not phraseologic_owned_frames_count:
        phraseologic_owned_frames_count = 0
    if not semantic_owned_frames_count:
        semantic_owned_frames_count = 0
    status_dict = {'status': status.status,
                   'owned_lemmas_count': owned_lemmas.count(),
                   'owned_frames_count': owned_frames_count,
                   'phraseologic_owned_lemmas_count': phraseologic_owned_lemmas.count(),
                   'phraseologic_owned_frames_count': phraseologic_owned_frames_count,
                   'semantic_owned_lemmas_count': semantic_owned_lemmas.count(),
                   'semantic_owned_frames_count': semantic_owned_frames_count}
    status_table_dict.append(status_dict)
    all_owned_frames_count += owned_frames_count
    all_phraseologic_owned_frames_count += phraseologic_owned_frames_count
    all_semantic_owned_frames_count += semantic_owned_frames_count
    
  lex_work_stats = get_lexical_stats(user)
  phraseology_work_stats = get_phraseology_stats(user)
  semantics_work_stats = get_semantics_stats(user)
  total_earned_cash = lex_work_stats['earned_cash']+phraseology_work_stats['earned_cash']+semantics_work_stats['earned_cash']
  return {'lemma_status_tab': status_table_dict,
          'all_owned_lemmas_count': all_owned_lemmas.count(),
          'all_owned_frames_count': all_owned_frames_count,
          'all_phraseologic_owned_lemmas_count': all_phraseologic_owned_lemmas.count(),
          'all_phraseologic_owned_frames_count': all_phraseologic_owned_frames_count,
          'all_semantic_owned_lemmas_count': all_semantic_owned_lemmas.count(),
          'all_semantic_owned_frames_count': all_semantic_owned_frames_count,
          'earned_cash': total_earned_cash,
          'paid_cash': round(user.user_stats.paid_cash, 2),
          'surcharge': round(user.user_stats.paid_cash-total_earned_cash, 2),
          'lex_work_stats': lex_work_stats,
          'phraseology_work_stats': phraseology_work_stats,
          'semantics_work_stats': semantics_work_stats}
  
def get_lexical_stats(user):
    earned_cash = RealizedLemma.objects.filter(user_stats__user=user).aggregate(Sum('cash'))['cash__sum']
    if earned_cash == None:
        earned_cash = 0.0
    lemmas_marked_to_erase = Lemma.objects.filter(owner=user, 
                                                  old=False, 
                                                  status__type__sym_name='erase')
    lemmas_to_erase_cash = 1.0*float(lemmas_marked_to_erase.count())
    earned_cash += lemmas_to_erase_cash
    
    bonus_cash = RealizedLemma.objects.filter(user_stats__user=user, 
                                              bonus=True).aggregate(Sum('cash'))['cash__sum']
    if bonus_cash == None:
        bonus_cash = 0.0        
    prop_frames = RealizedLemma.objects.filter(user_stats__user=user, 
                                               paid=False).aggregate(Sum('prop_frames'))['prop_frames__sum']
    if prop_frames == None:
        prop_frames = 0
    wrong_frames = RealizedLemma.objects.filter(user_stats__user=user, 
                                                paid=False).aggregate(Sum('wrong_frames'))['wrong_frames__sum']
    if wrong_frames == None:
        wrong_frames = 0
    corr_frames = RealizedLemma.objects.filter(user_stats__user=user, 
                                               paid=False).aggregate(Sum('corr_frames'))['corr_frames__sum']
    if corr_frames == None:
        corr_frames = 0
    ncorr_frames = RealizedLemma.objects.filter(user_stats__user=user, 
                                               paid=False).aggregate(Sum('ncorr_frames'))['ncorr_frames__sum']
    if ncorr_frames == None:
        ncorr_frames = 0
    made_frames = RealizedLemma.objects.filter(user_stats__user=user, 
                                               paid=False).aggregate(Sum('made_frames'))['made_frames__sum']
    if made_frames == None:
        made_frames = 0
      
    efficacy = 0.0
    if prop_frames+wrong_frames > 0:
        efficacy = float(prop_frames)/float(prop_frames+wrong_frames)*100.0
        
    
    lex_work_stats = {'earned_cash': round(earned_cash, 2),
                      'bonus_cash' : round(bonus_cash, 2),
                      'lemmas_to_erase_cash': round(lemmas_to_erase_cash, 2),
                      'prop_frames': prop_frames,
                      'wrong_frames': wrong_frames,
                      'corr_frames': corr_frames,
                      'checked_frames': ncorr_frames+corr_frames,
                      'made_frames'   : made_frames,
                      'efficacy'      : round(efficacy, 2)}
    return lex_work_stats    
    
    
def get_phraseology_stats(user):
    added_bindings = RealizedPhraseologyBinding.objects.filter(user_stats__user=user)
    used_bindings = get_used_bindings(added_bindings)
    
    earned_cash_frames = RealizedPhraseology.objects.filter(user_stats__user=user).aggregate(Sum('cash'))['cash__sum']
    if earned_cash_frames == None:
        earned_cash_frames = 0.0
    earned_cash_bindings = used_bindings.aggregate(Sum('cash'))['cash__sum']
    if earned_cash_bindings == None:
        earned_cash_bindings = 0.0
    earned_cash = earned_cash_frames+earned_cash_bindings
    bonus_cash = RealizedPhraseology.objects.filter(user_stats__user=user, 
                                                    bonus=True).aggregate(Sum('cash'))['cash__sum']
    if bonus_cash == None:
        bonus_cash = 0.0
    
    prop_frames = RealizedPhraseology.objects.filter(user_stats__user=user, 
                                               paid=False).aggregate(Sum('prop_frames'))['prop_frames__sum']
    if prop_frames == None:
        prop_frames = 0
    wrong_frames = RealizedPhraseology.objects.filter(user_stats__user=user, 
                                                paid=False).aggregate(Sum('wrong_frames'))['wrong_frames__sum']
    if wrong_frames == None:
        wrong_frames = 0
    corr_frames = RealizedPhraseology.objects.filter(user_stats__user=user, 
                                               paid=False).aggregate(Sum('corr_frames'))['corr_frames__sum']
    if corr_frames == None:
        corr_frames = 0
    ncorr_frames = RealizedPhraseology.objects.filter(user_stats__user=user, 
                                               paid=False).aggregate(Sum('ncorr_frames'))['ncorr_frames__sum']
    if ncorr_frames == None:
        ncorr_frames = 0
        
    new_frames = RealizedPhraseology.objects.filter(user_stats__user=user, 
                                               paid=False).aggregate(Sum('new_frames'))['new_frames__sum']
    if new_frames == None:
        new_frames = 0
        
    reused_frames = RealizedPhraseology.objects.filter(user_stats__user=user, 
                                               paid=False).aggregate(Sum('reused_frames'))['reused_frames__sum']
    if reused_frames == None:
        reused_frames = 0
                                               
    efficacy = 0.0
    if prop_frames+wrong_frames > 0:
        efficacy = float(prop_frames)/float(prop_frames+wrong_frames)*100.0
    
    phraseologic_empty_frame_value = 1.0
    made_phraseologic_empty_entries = user.user_stats.made_phraseologic_empty_entries_count()
    checked_phraseologic_empty_entries = user.user_stats.checked_phraseologic_empty_entries_count()
    earned_cash += phraseologic_empty_frame_value*float(made_phraseologic_empty_entries+checked_phraseologic_empty_entries)
      
    phraseology_work_stats = {'earned_cash': round(earned_cash, 2),
                              'bonus_cash' : round(bonus_cash, 2),
                              'prop_frames': prop_frames,
                              'wrong_frames': wrong_frames,
                              'corr_frames': corr_frames,
                              'checked_frames': ncorr_frames+corr_frames,
                              'new_frames'   : new_frames,
                              'reused_frames': reused_frames,
                              'added_bindings': added_bindings.count(),
                              'used_bindings':  used_bindings.count(),
                              'made_phraseologic_empty_entries': made_phraseologic_empty_entries,
                              'checked_phraseologic_empty_entries': checked_phraseologic_empty_entries,
                              'efficacy'      : round(efficacy, 2)}
    return phraseology_work_stats 

def get_used_bindings(added_bindings):
    unused_bindings = []
    for added_binding in added_bindings.all():
        binded_entry = added_binding.binded_entry
        act_binded_lemma = binded_entry.lemmas.get(old=False)
        if act_binded_lemma.status.type.sym_name == 'erase':
            unused_bindings.append(added_binding.pk)
        else:
            added_frame = added_binding.phraseologic_frame
            act_lemma_phras_frames = act_binded_lemma.frames.filter(phraseologic=True)
            act_lemma_phras_frames = act_lemma_phras_frames.annotate(positions_count=Count('positions'))
            act_lemma_phras_frames = act_lemma_phras_frames.filter(positions_count=added_frame.positions.count())
            for pos in added_frame.positions.all():
                act_lemma_phras_frames = act_lemma_phras_frames.filter(positions__text_rep=pos.text_rep)
                if not act_lemma_phras_frames.exists():
                    unused_bindings.append(added_binding.pk)
                    break
    return added_bindings.exclude(pk__in=unused_bindings)

def get_semantics_stats(user):
    earned_cash = RealizedSemantics.objects.filter(user_stats__user=user).aggregate(Sum('cash'))['cash__sum']
    if earned_cash == None:
        earned_cash = 0.0
    
    bonus_cash = RealizedSemantics.objects.filter(user_stats__user=user, 
                                                  bonus=True).aggregate(Sum('cash'))['cash__sum']
    if bonus_cash == None:
        bonus_cash = 0.0        
    prop_frames = RealizedSemantics.objects.filter(user_stats__user=user).aggregate(Sum('prop_frames'))['prop_frames__sum']
    if prop_frames == None:
        prop_frames = 0
    part_prop_frames = RealizedSemantics.objects.filter(user_stats__user=user).aggregate(Sum('part_prop_frames'))['part_prop_frames__sum']
    if part_prop_frames == None:
        part_prop_frames = 0
    wrong_frames = RealizedSemantics.objects.filter(user_stats__user=user).aggregate(Sum('wrong_frames'))['wrong_frames__sum']
    if wrong_frames == None:
        wrong_frames = 0
    corr_frames = RealizedSemantics.objects.filter(user_stats__user=user).aggregate(Sum('corr_frames'))['corr_frames__sum']
    if corr_frames == None:
        corr_frames = 0  
    part_corr_frames = RealizedSemantics.objects.filter(user_stats__user=user).aggregate(Sum('part_corr_frames'))['part_corr_frames__sum']
    if part_corr_frames == None:
        part_corr_frames = 0
    ncorr_frames = RealizedSemantics.objects.filter(user_stats__user=user).aggregate(Sum('ncorr_frames'))['ncorr_frames__sum']
    if ncorr_frames == None:
        ncorr_frames = 0
    made_frames = RealizedSemantics.objects.filter(user_stats__user=user).aggregate(Sum('made_frames'))['made_frames__sum']
    if made_frames == None:
        made_frames = 0   
    added_connections = RealizedSemantics.objects.filter(user_stats__user=user).aggregate(Sum('added_connections'))['added_connections__sum']
    if added_connections == None:
        added_connections = 0
    efficacy = 0.0
    if prop_frames+wrong_frames > 0:
        efficacy = float(prop_frames)/float(prop_frames+wrong_frames)*100.0
    
    sem_work_stats = {'earned_cash': round(earned_cash, 2),
                      'bonus_cash': round(bonus_cash, 2),
                      'prop_frames': prop_frames,
                      'part_prop_frames': part_prop_frames,
                      'wrong_frames': wrong_frames,
                      'corr_frames': corr_frames,
                      'part_corr_frames': part_corr_frames,
                      'checked_frames': ncorr_frames+corr_frames+part_corr_frames,
                      'made_frames': made_frames,
                      'efficacy': round(efficacy, 2),
                      'added_connections' : added_connections}
    return sem_work_stats    
