# %%
PROJECT_PATH = '/home/md/Work/ligalytics/leagues_stable/'
import os, sys
sys.path.insert(0, PROJECT_PATH)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "leagues.settings")
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
import random
import time

# XPRESS ENVIRONMENT
os.environ['XPRESSDIR'] = "/opt/xpressmp_8.4"
os.environ['XPRESS'] = "/opt/xpressmp_8.4/bin"
os.environ['LD_LIBRARY_PATH'] = os.environ['XPRESSDIR']+"/lib:"+os.environ['LD_LIBRARY_PATH']
os.environ['DYLD_LIBRARY_PATH'] = os.environ['XPRESSDIR']+"/lib:"
os.environ['SHLIB_PATH'] = os.environ['XPRESSDIR']+"/lib:"
os.environ['LIBPATH'] = os.environ['XPRESSDIR']+"/lib:"
# os.environ['PYTHONPATH'] =os.environ['XPRESSDIR']+"/lib:"+os.environ['PYTHONPATH']
os.environ['PYTHONPATH'] =os.environ['XPRESSDIR']+"/lib:"
os.environ['CLASSPATH'] =os.environ['XPRESSDIR']+"/lib/xprs.jar:"
os.environ['CLASSPATH'] =os.environ['XPRESSDIR']+"/lib/xprb.jar:"+os.environ['CLASSPATH']
os.environ['CLASSPATH'] =os.environ['XPRESSDIR']+"/lib/xprm.jar:"+os.environ['CLASSPATH']
os.environ['PATH'] =os.environ['XPRESSDIR']+"/bin:"+os.environ['PATH']


from leagues import settings
settings.DATABASES['default']['NAME'] = PROJECT_PATH+'/db.sqlite3'

import django
django.setup()

from scheduler.models import *
from pulp import *
import csv
import networkx as nx
from multiprocessing import Pool, cpu_count


import xpress as xp
# xp.controls.outputlog = 0


# %%

# n = 1000

def simulate_draws(filename,n):

    print("RUNNING ASYNC",filename)

    f = open(f"infeasible/{filename}_{0}.html", "w")

    for i in range(1, n):
        if i % 100 == 0:
            print("RUNNING ASYNC",filename,i)            
            f.close()
            f = open(f"infeasible/{filename}_{i}.html", "w")

        # write html to file
        # filename = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
        # with open(f"infeasible/{i}.html", "w") as f:

        teams = [
        {'id': 'A1', 'country': '0', 'pot': 1, 'name': 'A1'} ,
        {'id': 'A2', 'country': '0', 'pot': 1, 'name': 'A2'} ,
        {'id': 'A3', 'country': '0', 'pot': 1, 'name': 'A3'} ,
        {'id': 'A4', 'country': '0', 'pot': 1, 'name': 'A4'} ,
        {'id': 'A5', 'country': '0', 'pot': 1, 'name': 'A5'} ,
        {'id': 'A6', 'country': '0', 'pot': 1, 'name': 'A6'} ,
        {'id': 'A7', 'country': '0', 'pot': 1, 'name': 'A7'} ,
        {'id': 'A8', 'country': '0', 'pot': 1, 'name': 'A8'} ,
        {'id': 'A9', 'country': '0', 'pot': 1, 'name': 'A9'} ,
        {'id': 'B1', 'country': '0', 'pot': 2, 'name': 'B1'} ,
        {'id': 'B2', 'country': '0', 'pot': 2, 'name': 'B2'} ,
        {'id': 'B3', 'country': '0', 'pot': 2, 'name': 'B3'} ,
        {'id': 'B4', 'country': '0', 'pot': 2, 'name': 'B4'} ,
        {'id': 'B5', 'country': '0', 'pot': 2, 'name': 'B5'} ,
        {'id': 'B6', 'country': '0', 'pot': 2, 'name': 'B6'} ,
        {'id': 'B7', 'country': '0', 'pot': 2, 'name': 'B7'} ,
        {'id': 'B8', 'country': '0', 'pot': 2, 'name': 'B8'} ,
        {'id': 'B9', 'country': '0', 'pot': 2, 'name': 'B9'} ,
        {'id': 'C1', 'country': '0', 'pot': 3, 'name': 'C1'} ,
        {'id': 'C2', 'country': '0', 'pot': 3, 'name': 'C2'} ,
        {'id': 'C3', 'country': '0', 'pot': 3, 'name': 'C3'} ,
        {'id': 'C4', 'country': '0', 'pot': 3, 'name': 'C4'} ,
        {'id': 'C5', 'country': '0', 'pot': 3, 'name': 'C5'} ,
        {'id': 'C6', 'country': '0', 'pot': 3, 'name': 'C6'} ,
        {'id': 'C7', 'country': '0', 'pot': 3, 'name': 'C7'} ,
        {'id': 'C8', 'country': '0', 'pot': 3, 'name': 'C8'} ,
        {'id': 'C9', 'country': '0', 'pot': 3, 'name': 'C9'} ,
        {'id': 'D1', 'country': '0', 'pot': 4, 'name': 'D1'} ,
        {'id': 'D2', 'country': '0', 'pot': 4, 'name': 'D2'} ,
        {'id': 'D3', 'country': '0', 'pot': 4, 'name': 'D3'} ,
        {'id': 'D4', 'country': '0', 'pot': 4, 'name': 'D4'} ,
        {'id': 'D5', 'country': '0', 'pot': 4, 'name': 'D5'} ,
        {'id': 'D6', 'country': '0', 'pot': 4, 'name': 'D6'} ,
        {'id': 'D7', 'country': '0', 'pot': 4, 'name': 'D7'} ,
        {'id': 'D8', 'country': '0', 'pot': 4, 'name': 'D8'} ,
        {'id': 'D9', 'country': '0', 'pot': 4, 'name': 'D9'} ,
        ]

        teams_dict = {t['id']:t for t in teams}


        country_groups = {}

        # country_groups = {
        # '1':['A1','A2','B1','B2','C1','C2','D1'],
        # '2':['A3','A4','A5','B3','B4','B5'],
        # '3':['A6','A7','A8','B6','B7','B8'],
        # '4':['C3','C4','C5','D3','D4','D5'],
        # '5':['C6','C7','C8','D6','D7','D8'],
        # '6':['A9','B9','C9','D9','D2'],
        # # '5':['A9','B9','C9','D5','D6'],
        # # '2':['A4','A5','A6','B4','B5','B6'],
        # # '3':['A7','A8','A9','B7','B8','B9'],
        # # '4':['C1','C2','C3','D1','D2','D3'],
        # # '5':['C4','C5','C6','D4','D5','D6'],
        # }

        for c in country_groups:
            for tc in country_groups[c]:
                for t in teams:
                    if t['id'] == tc:
                        t['country'] = c


        if not country_groups:

            nCr = 5


            n_country = {
                (c,p):0 for c in range(1,nCr+1) for p in range(1,5)
            }

            for t in teams:
                samples = list(range(1,nCr+1))
                random.shuffle(samples)
                found = False
                while(samples and not found):
                    random_country = samples.pop()
                    total_random_countries = sum(n_country[random_country,p] for p in range(1,5))

                    if total_random_countries >= 7:            
                        pass
                    if max([n_country[random_country,p] for p in range(1,5)]) >= 9 - (total_random_countries+1):
                        pass                
                    else:
                        t['country'] = random_country
                        n_country[random_country,t['pot']] += 1
                        found = True


            x_counter = 0
            x_index = 1
            for t in teams:
                if t['country'] not in list(range(1,nCr+1)):
                    if x_counter < 4:
                        x_counter += 1
                    else:
                        x_index += 1
                        x_counter = 1
                    t['country'] = f'X{x_index}'





        # %%



        getTeamById = {}
        getNameById = {}
        getCountryById = {}
        for t in teams:
            getTeamById[t['id']] = f"({t['pot']}) {t['name']}"
            getCountryById[t['id']] = t['country']
            getNameById[t['id']] = t['name']


        countries = list(set(t['country'] for t in teams))
        teams_from_country = {
            c:[t for t in teams if t['country']==c] for c in countries 
        }

        pot = {i:[] for i in range(1,5)}
        teams_from_pot = {i:[] for i in range(1,5)}
        team_ids_from_pot = {i:[] for i in range(1,5)}
        for t in teams:
            pot[t['pot']].append(t)
            teams_from_pot[t['pot']].append(t)
            team_ids_from_pot[t['pot']].append(t['id'])
            

        teams = list(teams)

        def check_feasible(fixed_games):
            model = xp.problem(name='Draws', sense=xp.minimize)
            model.setControl ('outputlog', 0)

            x = {}
            for t1 in teams:
                for t2 in teams:
                    if t1['country'] != t2['country']:
                        x[t1['id'], t2['id']] = xp.var(ub=1, vartype=xp.integer)

            model.addVariable(x)

            # REQUIREMENTS
            for t in teams:
                for r in range(1,5):
                    model.addConstraint(xp.Sum(x[t['id'],t2['id']] for t2 in pot[r] if (t['id'],t2['id']) in x.keys()) == 1)
                    model.addConstraint(xp.Sum(x[t2['id'],t['id']] for t2 in pot[r] if (t2['id'],t['id']) in x.keys()) == 1)
                for c in countries:
                    if c != t['country']:
                        model.addConstraint(xp.Sum(x[t['id'],t2['id']]+x[t2['id'],t['id']] for t2 in teams_from_country[c]) <= 2)

            # FIXATIONS
            for (t1,t2) in fixed_games:
                # print("FIXING",t1,t2)
                model.addConstraint(x[t1,t2] == 1)


            for (t1,t2) in x.keys():
                model.addConstraint(x[t1,t2] + x[t2,t1] <= 1)

            start_time = time()
            model.solve()
            comp_time = time()-start_time

            if model.getProbStatus() != 6:
                # print("INFEASIBLE FOUND")
                return False
            else:
                fixed_games = [(i,j) for (i,j) in x.keys() if model.getSolution(x[(i,j)]) == 1]        
                return fixed_games


        fixed_games = check_feasible([])

        # print(fixed_games)


        # if not fixed_games:
        if True:

            html = f"<h1>{i}</h1>"
            html += "<table>"
            html += " \
            <style>     \
                table, th, td {     \
                        border: 1px solid black;     \
                        border-collapse: collapse;     \
                        text-align: center;     \
                        min-width:40px;     \
                        padding:3px;     \
                        margin: 3px;     \
                        font-family : Verdana, sans-serif;\
                }     \
                h1 {\
                    font-family : Verdana, sans-serif;\
                }\
            </style> \
            "

            color = {
                '0':'#000000',
                '1':'#FF0000',
                '2':'#00FF00',
                '3':'#0000FF',
                '4':'#FFFF00',
                '5':'#FF00FF',
                '6':'#00FFFF',
                '7':'#777777',
                '8':'#FFFFFF',
                '9':'#FFA500',
                'X1':'#CCCCCC',
                'X2':'#AAAAAA',
                'X3':'#888888',
                'X4':'#666666',
                'X5':'#444444',
            }

            font = defaultdict(lambda: '#000000')
            font['0'] = '#FFFFFF'



            html += "<tr><td></td>"
            for j in range(1,10):
                html += f"<td>{j}</td>"
            html += "</tr>"
            for i in ['A','B','C','D']:
                html += f"<tr><td>{i}</td>"
                for j in range(1,10):        
                    team = teams_dict[f"{i}{j}"]
                    html += f"<td style='color:{font[str(team['country'])]};background-color:{color[str(team['country'])]}'>{team['id']}</td>"
                html += "</tr>"
            html += "</table>"

        
            # with open(f"infeasible/table.html", "w") as f:
            if not fixed_games:
                print("\tRUNNING ASYNC",filename,i,"\tINFEASIBLE FOUND")
                html += f"<h1>INFEASIBLE FOUND</h1>"
            html += "<br><br>"

            f.write(html)


n = sys.maxsize

pool = Pool()
result = {}
answer = {}

for cpu in range(cpu_count()):
    result[cpu] = pool.apply_async(simulate_draws, args=(f'thread_{cpu}', n,))

for cpu in range(cpu_count()):
    answer[cpu] = result[cpu].get()





# # # SOLUTION


# opponents = {t['name']:[] for t in teams}
# for g in fixed_games:
#     opponents[getNameById[g[0]]].append(getNameById[g[1]])
#     opponents[getNameById[g[1]]].append(getNameById[g[0]])


# for t in teams:
#     opponents[t['name']] = list(set(opponents[t['name']]))

# # %%

# cells = {
#     (i,j):[] for i in ['A','B','C','D'] for j in range(1,10)
# }

# for team in teams:
#     for opponent in opponents[team['name']]:
#         cells[(opponent[0],int(opponent[1]))].append(team['name'])
        


# html = "<table>"
# html += " \
# <style>     \
#     table, th, td {     \
#             border: 1px solid black;     \
#             border-collapse: collapse;     \
#             text-align: center;     \
#             min-width:40px;     \
#             padding:3px;     \
#             margin: 3px;     \
#             font-family : Verdana, sans-serif;\
#     }     \
#     h1 {\
#         font-family : Verdana, sans-serif;\
#     }\
# </style> \
# "

# color = {
#     '1':'#FF0000',
#     '2':'#00FF00',
#     '3':'#0000FF',
#     '4':'#FFFF00',
#     '5':'#FF00FF',
#     '6':'#00FFFF',
#     '7':'#777777',
#     '8':'#FFFFFF',
#     '9':'#FFA500',
# }



# html += "<tr><td></td>"
# for j in range(1,10):
#     html += f"<td style='background-color:{color[str(j)]}'>{j}</td>"
# html += "</tr>"
# for i in ['A','B','C','D']:
#     html += f"<tr><td>{i}</td>"
#     for j in range(1,10):        
#         html += f"<td>"
#         for e in sorted(cells[(i,j)]):
#             if e in ['A1','A2','B1','B2','C1','C2','D1']:
#                 html += f"<span style='background-color:{color[e[1]]}'>{e}</span><br>"
#         html+=f"</td>"
#     html += "</tr>"
# html += "</table>"


# # for g in fixed_games:
# #     if getNameById[g[0]] in ['A1','A2'] or getNameById[g[1]] in ['A1','A2']:
# #         print(getTeamById[g[0]],getTeamById[g[1]])


# # print("\n\n")

# # for g in fixed_games:
# #     if getNameById[g[0]] in ['B1','B2'] or getNameById[g[1]] in ['B1','B2']:
# #         print(getTeamById[g[0]],getTeamById[g[1]])

# # print("\n\n")

# # for g in fixed_games:
# #     if getNameById[g[0]] in ['C1','C2'] or getNameById[g[1]] in ['C1','C2']:
# #         print(getTeamById[g[0]],getTeamById[g[1]])


# # print("\n\n")

# # for g in fixed_games:
# #     if getNameById[g[0]] in ['D1'] or getNameById[g[1]] in ['D1']:
# #         print(getTeamById[g[0]],getTeamById[g[1]])



# # %%
# connected_components= {}
# t_pot ={ t['id'] : t['pot'] for t in teams}
# pots=sorted(list(set(t['pot'] for t in teams)))
# for p1 in pots:
#     for p2 in pots:
#         if p1<=p2:
#             # print ("POTS ",p1, p2, ":")
#             theseGames= [ (t1,t2) for (t1,t2) in fixed_games if (t_pot[t1],t_pot[t2]) in [(p1,p2),(p2,p1)] ]
#             G = nx.Graph(theseGames)
#             cntr=0
#             connected_components[p1,p2]=""
#             for c in nx.connected_components(G):
#                 cntr+=1
#                 # print ("  COMP" ,cntr,  list (c))
#                 connected_components[p1,p2]+=str(len(c))+", "
#             connected_components[p1,p2]=connected_components[p1,p2][:-2]
#             connected_components[p2,p1]=connected_components[p1,p2]


# extraTable = "<table><tr><th>&nbsp; </th>"
# for p1 in pots:
#     extraTable += "<th style='width:150px'> Pot " + str(p1)+ "</th>"
# extraTable += "</tr>"

# for p1 in pots:
#     extraTable += "<tr><th style='width:150px'> Pot " + str(p1)+ "</th>"
#     for p2 in pots:
#         extraTable += "<td> " +connected_components[p1,p2] + "</td>"
#     extraTable += "</tr>"
# extraTable += "</table>"



# # write html to file
# with open("table.html", "w") as f:
#     f.write(html)
#     f.write("<br><br>")
#     f.write(extraTable)


# # %%
