from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
import json
import csv

from scheduler.models import *
from scheduler.views_func import ComputationProgressView
from .ml.learners import AttendanceLearner
from .simulator.simulator import UefaSimulator


def histgames(request):
    games = Game.objects.filter(season=request.session['season'])
    context = {
        'games': games
    }
    return render(request, 'historic_games.html', context)


def master_attendance(request):
    if request.method == 'GET':
        season = Season.objects.filter(id=request.session['season'])
        context = {
            'season': season
        }
        return render(request, 'attendance.html', context)

    elif request.method == "POST":
        if request.POST['type'] == 'train':
            print("TRAINING")
            learner = AttendanceLearner(request.session['season'])
            learner.train()
            learner.save()
            return JsonResponse({'score': learner.score})
        elif request.POST['type'] == 'predict':
            print("PREDICT")
            scenario = Scenario.objects.get(id=request.session['scenario'])

            def createGamesFromSolution(scenario_id):
                scenario = Scenario.objects.get(id=scenario_id)
                season = scenario.season

                games = []
                Game.objects.filter(
                    season=season, historic_season=None).delete()
                for game in scenario.solutionlist():
                    day = Day.objects.get(id=game[0])
                    home = Team.objects.get(id=game[1])
                    away = Team.objects.get(id=game[2])
                    round = game[3]
                    time = game[4]
                    games.append(Game(
                        season=season,
                        homeTeam=home,
                        awayTeam=away,
                        round=round,
                        date=parse(day.day),
                        time=time,
                    ))
                Game.objects.bulk_create(games)

            createGamesFromSolution(scenario.id)

            learner = AttendanceLearner(request.session['season'])
            learner.load()
            learner.predict()

            games = Game.objects.filter(
                season=scenario.season, historic_season=None)
            for g in games:
                g.attendance = learner.predictions[g.id]
                g.save()

            return JsonResponse({})


def simulator(request):

    if request.method == "GET":
        scenario = Scenario.objects.get(id=request.session['scenario'])

        response = json.loads(ComputationProgressView(request).content)        
        progress = response['task_status'] if 'task_status' in response else ""
        
        scenarios = []
        scenarios_exist = []
        all_kpis = []
        get_kpi = defaultdict(lambda:{})
        get_kpi_text = defaultdict(lambda:{})
        if scenario.sim_report:            
            kpis = json.loads(scenario.sim_report) 
            scenarios = list(kpis.keys())[1:]
            for s in scenarios:
                for kpi in [kpit.split("__") for kpit in kpis[s].split("___")]:
                    if not kpi[0] in all_kpis:
                        all_kpis.append(kpi[0])
                

            get_kpi_val = { (s,kpi) : 0  for s in scenarios for kpi in all_kpis}

            for s in scenarios:
                scenarioObj = Scenario.objects.filter(id=s).first()      
                kpis_dict = {}   
                if scenarioObj:              
                    scenarios_exist.append(str(scenarioObj.id))
                    # If exists update with most recent data
                    if scenarioObj.sol_kpis != "":
                        for kpi in scenarioObj.kpis():
                            kpis_dict[kpi[0]] = kpi[1:]
                        kpis_dict["Datetime"] = [scenarioObj.lastComputation.strftime('%Y:%m:%d-%H:%M:%S'),""]
                    
                    
                for kpi in [kpit.split("__") for kpit in kpis[s].split("___")]:
                    des1=kpi[0]     
                    val1= kpis_dict[des1][0] if des1 in kpis_dict else kpi[1]
                    get_kpi[s][des1]= val1
                    val1=(val1.split(" "))[0]
                    if val1.isnumeric():
                        get_kpi_val[(s, des1)]= int(float(val1))
                        if len(kpi)>2:
                            if des1 in kpis_dict and len(kpis_dict[des1])>1:
                                get_kpi_text[s][des1]= kpis_dict[des1][1]
                            else:
                                get_kpi_text[s][des1]= kpi[2]
                    # else:
                    #     get_kpi_text[s][des1] = val1 
                    # 

            all_kpis=[kpi for kpi in all_kpis if len([sc for sc in scenarios if get_kpi[sc][kpi] != "0 of 0" ])>0]



        context = {
            'scenario': scenario,
            'scenarios':scenarios,
            'scenarios_exist':scenarios_exist,
            'all_kpis':all_kpis,
            'get_kpi': get_kpi,
            'get_kpi_text': get_kpi_text,
            'progress':progress
        }
        return render(request, "simulator.html", context)

    elif request.method == "POST":

        if request.POST['method'] == "submit_params":
            s = Scenario.objects.get(id=request.session['scenario'])
            s.sim_script = request.POST['payload'].replace("\n", ";").replace("\"","").replace("\'","")
            s.save()
            return HttpResponse("OK")

        elif request.POST['method'] == "start_simulation":
            s = Scenario.objects.get(id=request.session['scenario'])
            sim = UefaSimulator(s.id)
            sim.simulate()
            return HttpResponse("OK")

        elif request.POST['method'] == "start_improvement":
            s = Scenario.objects.get(id=request.session['scenario'])
            sim = UefaSimulator(s.id)
            sim.improve()
            return HttpResponse("OK")


def findall(p, s):
    i = s.find(p)
    while i != -1:
        yield i
        i = s.find(p, i+1)


def simulation_report(request):

        baseScenario = Scenario.objects.get(id=request.session['scenario'])            

        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="{}_{}_violations.csv"'.format(baseScenario.season.nicename,baseScenario.name)

        writer = csv.writer(response,delimiter=",")

        # writer.writerow(['', 'Team Name', 'Date', 'Type', 'Time', 'Comment', 'Tag'])            
        # for b in Blocking.objects.filter(scenario=scenario):
        #     writer.writerow(["BLOCKING",b.team.name,parse(b.day.day).date(),b.type,b.time,b.comment,b.tag])

        prioVal ={'A': 25 , 'B': 5 , 'C': 1, 'Hard' : 1000}

        quality_dict = {}
        for ref_scenario in baseScenario.simulation_scenarios.all().order_by('name'):
            for scenario in ref_scenario.simulation_scenarios.all().order_by('name').reverse():

                total_vio = 0
                objectiveFunctionWeights = ObjectiveFunctionWeight.objects.filter(scenario=scenario).values()

                gew={}  
                for ow in objectiveFunctionWeights:
                    gew[ow['name']]= ow['use'] * ow['prio']


                if scenario.sol_kpis != "":   
                    kpis_dict = {}  
                    for kpi in scenario.kpis():
                        kpis_dict[kpi[0]] = kpi[1:]
                    kpis_dict["Datetime"] = [scenario.lastComputation.strftime('%Y:%m:%d-%H:%M:%S'),""]


                uclpatterns = SpecialWish.objects.filter(scenario=scenario,name='UCL24Patterns',active=True).exists()
                quality_scen = {"Overall Quality":kpis_dict["Overall Quality"],"Datetime":kpis_dict["Datetime"],"UCLpatterns":[uclpatterns]}
                first_row = ["" for i in range(5)]

                # PRIO BASED
                # for prio in ['Hard','A','B','C']:
                #     pairing_vios = Pairing.objects.filter(scenario=scenario,prio=prio,active=True).exclude(violation="")
                #     pairing_viols_count = 0
                #     for v in pairing_vios:
                #         pairing_viols_count += len(v.violation.split("__"))
                #     quality_scen["Pairing"][prio] = [pairing_viols_count,5*prioVal[prio] * pairing_viols_count * gew["Pairings"]]
                #     total_vio += 5*prioVal[prio] * pairing_viols_count * gew["Pairings"]
                    
                #     ha_vios = HAWish.objects.filter(scenario=scenario,prio=prio,active=True).exclude(violation="")
                #     ha_vios_count = 0
                #     for v in ha_vios:                            
                #         many = {}
                #         few = {}
                #         for i in range(10):
                #             many[i] = len(list(findall(f"{i} too many",v.violation)))
                #             few[i] = len(list(findall(f"{i} too few",v.violation)))
                #             ha_vios_count += i*(many[i] + few[i])
                #     quality_scen["HAWish"][prio]  = [ha_vios_count,prioVal[prio] * ha_vios_count * gew["Home-/Away"]]
                #     total_vio += prioVal[prio] * ha_vios_count * gew["Home-/Away"]

                #     enc_vios = EncWish.objects.filter(scenario=scenario,prio=prio,active=True).exclude(violation="").exclude(violation="Not evaluated yet!")
                #     enc_vios_count = 0
                #     for v in enc_vios:
                #         many = {}
                #         few = {}
                #         for i in range(10):
                #             many[i] = len(list(findall(f"{i} too many",v.violation)))
                #             few[i] = len(list(findall(f"{i} too few",v.violation)))
                #             enc_vios_count += i*(many[i] + few[i])

                #             # for a in s.split(":"):
                #             #     if "too" in a:
                #             #         print("\t",a)
                #                     # ha_vios_count += int(a.split("too")[0].strip())
                #     # quality_scen["HAWish"][prio]  = [ha_vios_count,prioVal[prio] * ha_vios_count * gew["Home-/Away"]]


                #     quality_scen["EncWish"][prio] = [enc_vios_count,5*prioVal[prio] * enc_vios_count * gew["Encounters"]]
                #     total_vio += 5*prioVal[prio] * enc_vios_count * gew["Encounters"]

                #     quality_scen["PAIR+HA+ENC"] = total_vio

                dynamic_rows = []


                """ PAIRINGS """                
                pairings = Pairing.objects.filter(scenario=scenario,active=True)
                pairing_tags = pairings.values_list('comment',flat=True).distinct()

                for tag in pairing_tags:
                    first_row.append("PAIRINGS")
                    row = f"{tag}"
                    dynamic_rows.append(row)
                    pairing_vios = pairings.filter(comment=tag).exclude(violation="")
                    pairing_viols_count = 0
                    pairing_viols_obj = 0
                    for v in pairing_vios:
                        pairing_viols_count += len(v.violation.split("__"))
                        pairing_viols_obj += 5*prioVal[v.prio] * len(v.violation.split("__"))
                    quality_scen[row] = [pairing_viols_count,pairing_viols_obj * gew["Pairings"]]
                    total_vio += pairing_viols_obj * gew["Pairings"]


                """ HOME AWAY """
                tags = Tag.objects.filter(season=scenario.season,scheduler_hawishes__isnull=False).distinct()

                for tag in tags:
                    first_row.append("HOME AWAY")
                    row = f"{tag.name}"
                    dynamic_rows.append(row)
                    ha_vios = tag.scheduler_hawishes.filter(scenario=scenario,active=True).exclude(violation="")
                    ha_vios_count = 0
                    ha_vios_obj = 0
                    for v in ha_vios:                            
                        many = {}
                        few = {}
                        for i in range(10):
                            many[i] = len(list(findall(f"{i} too many",v.violation)))
                            few[i] = len(list(findall(f"{i} too few",v.violation)))
                            ha_vios_count += i*(many[i] + few[i])
                            ha_vios_obj += i*(many[i] + few[i]) * prioVal[v.prio]
                    quality_scen[row]  = [ha_vios_count, ha_vios_obj * gew["Home-/Away"]]
                    total_vio += ha_vios_obj * gew["Home-/Away"]


                """ ENCOUNTERS """
                tags = Tag.objects.filter(season=scenario.season,scheduler_encwishes__isnull=False).distinct()

                for tag in tags:
                    first_row.append("ENCOUNTERS")
                    row = f"{tag.name}"
                    dynamic_rows.append(row)
                    # enc_vios = EncWish.objects.filter(scenario=scenario,prio=prio,active=True).exclude(violation="").exclude(violation="Not evaluated yet!")
                    enc_vios = tag.scheduler_encwishes.filter(scenario=scenario,active=True).exclude(violation="").exclude(violation="Not evaluated yet!")
                    enc_vios_count = 0
                    enc_vios_obj = 0
                    for v in enc_vios:
                        many = {}
                        few = {}
                        for i in range(10):
                            many[i] = len(list(findall(f"{i} too many",v.violation)))
                            few[i] = len(list(findall(f"{i} too few",v.violation)))
                            enc_vios_count += i*(many[i] + few[i])
                            enc_vios_obj += i*(many[i] + few[i]) * prioVal[v.prio] * 5
                            # for a in s.split(":"):
                            #     if "too" in a:
                            #         print("\t",a)
                                    # ha_vios_count += int(a.split("too")[0].strip())
                    # quality_scen["HAWish"][prio]  = [ha_vios_count,prioVal[prio] * ha_vios_count * gew["Home-/Away"]]
                    quality_scen[row] = [enc_vios_count,enc_vios_obj * gew["Encounters"]]
                    total_vio += enc_vios_obj * gew["Encounters"]

                quality_scen["PAIR+HA+ENC"] = total_vio



                quality_dict[scenario.name] = quality_scen


        writer.writerow(first_row[:5]+[""]+first_row[5:]+[""]+first_row[5:])
        rows = ["AScenario","Datetime","UCLPatterns","Overall Quality","PAIR+HA+ENC"]
        rows += [""]
        rows += [f"#({r})" for r in dynamic_rows]
        rows += [""]
        rows += [f"obj({r})" for r in dynamic_rows]
        writer.writerow(rows)

        for scenario in quality_dict.keys():
            ll = []
            ll.append(f"{scenario}")
            ll.append(f"{quality_dict[scenario]['Datetime'][0]}")
            ll.append(f"{quality_dict[scenario]['UCLpatterns'][0]}")
            ll.append(f"{quality_dict[scenario]['Overall Quality'][0]}")
            ll.append(f"{quality_dict[scenario]['PAIR+HA+ENC']}")
            ll.append("")
            for row in dynamic_rows:                
                ll.append(f"{quality_dict[scenario][row][0]}")
            ll.append("")
            for row in dynamic_rows:                
                ll.append(f"{quality_dict[scenario][row][1]}")                
            writer.writerow(ll)
            



        return response