#!/usr/bin/env python3
# Generátor výsledkové listiny pro MO-P

import argparse
import locale
from sqlalchemy.orm import joinedload

import mo.db as db
from mo.score import Score
from mo.util import die, init_standalone
from mo.util_format import format_decimal

parser = argparse.ArgumentParser(description='Vygeneruje výsledkovou listinu MO-P')
parser.add_argument('year', type=int)
parser.add_argument('seq', type=int)

args = parser.parse_args()
init_standalone()
sess = db.get_session()


def get_results(round, contests):
    results = {}
    for contest in contests:
        place_code = contest.place.get_code()
        print(f"Počítám oblast {place_code}")

        score = Score(round, contest)
        results[place_code] = score.get_sorted_results()

        for msg in score.get_messages():
            if msg[0] != 'info':
                print(f'\t{msg[0].upper()}: {msg[1]}')

    return results


def write_tex(round, tasks, contests, results):
    with open('final.tex', 'w') as out:
        out.write(r'\def\HranicePostupu{%s}' % (format_decimal(round.score_winner_limit,)) + "\n")
        out.write(r'\def\HraniceUspesnychResitelu{%s}' % (format_decimal(round.score_successful_limit),) + "\n")
        out.write('\n')
        for c in contests:
            res = results[c.place.get_code()]
            if round.seq <= 2:
                out.write(r'\kraj{%s}' % c.place.name + '\n')
                if not res:
                    out.write(r'\nobody' + '\n')
                    out.write(r'\endkraj' + '\n\n')
                    continue

            out.write(r'\begintable' + '\n')
            prev_typ = ""

            for r in res:
                if r.winner:
                    typ = 'v'
                elif r.successful:
                    typ = 'u'
                else:
                    typ = 'n'
                if typ != prev_typ:
                    if prev_typ:
                        out.write(r'\sep%s' % typ)
                    prev_typ = typ
                out.write(r'\%s' % typ)

                cols = []
                o = r.order
                if not r.successful or o.continuation:
                    cols.append("")
                elif o.span > 1:
                    cols.append(f'{o.place}.--{o.place + o.span - 1}.')
                else:
                    cols.append(f'{o.place}.')

                cols.append(r.user.full_name())
                cols.append(r.pant.school_place.name)
                cols.append(r.pant.grade)

                sol_map = r.get_sols_map()
                for t in tasks:
                    s = sol_map.get(t.task_id)
                    if s is not None:
                        cols.append(format_decimal(s.points))
                    else:
                        cols.append('--')

                cols.append(format_decimal(r.get_total_points()))

                out.write("".join(['{' + str(col) + '}' for col in cols]) + '\n')

            out.write(r'\endtable' + '\n')
            if round.seq <= 2:
                out.write(r'\endkraj' + '\n\n')


def write_html(round, tasks, contests, results):
    num_cols = 4 + len(tasks) + 1
    with open('final.html', 'w') as out:
        for c in contests:
            out.write(f'<tr><th colspan={num_cols}>{c.place.name}\n')

            res = results[c.place.get_code()]
            if not res:
                out.write(f'<tr class=nobody><td colspan={num_cols}>Nikdo se nezúčastnil.\n')
                out.write(f'<tr><td colspan={num_cols}>\n\n')
                continue

            for r in res:
                if r.winner:
                    out.write('<tr class=marked>')
                elif r.successful:
                    out.write('<tr class=success>')
                else:
                    out.write('<tr>')

                cols = []
                o = r.order
                if not r.successful or o.continuation:
                    cols.append("")
                elif o.span > 1:
                    cols.append(f'{o.place}.–{o.place + o.span - 1}.')
                else:
                    cols.append(f'{o.place}.')

                cols.append(r.user.full_name())
                cols.append(r.pant.school_place.name)
                cols.append(r.pant.grade)

                sol_map = r.get_sols_map()
                for t in tasks:
                    s = sol_map.get(t.task_id)
                    if s is not None:
                        cols.append(format_decimal(s.points))
                    else:
                        cols.append('–')

                cols.append(format_decimal(r.get_total_points()))

                out.write("".join(['<td>' + str(col) for col in cols]) + '\n')

            out.write(f'<tr><td colspan={num_cols}>\n\n')


round = sess.query(db.Round).filter_by(year=args.year, category='P', seq=args.seq).filter(db.Round.master_round_id == db.Round.round_id).one()
print(f"Kolo {round.round_code()}")

round_group_subq = sess.query(db.Round.round_id).filter_by(master_round_id=round.round_id)
tasks = sess.query(db.Task).filter(db.Task.round_id.in_(round_group_subq)).order_by(db.Task.code).all()

contests = (sess.query(db.Contest)
            .filter_by(round=round)
            .options(joinedload(db.Contest.place))
            .all())
assert contests
contests.sort(key=lambda c: locale.strxfrm(c.place.name))

results = get_results(round, contests)
write_tex(round, tasks, contests, results)
write_html(round, tasks, contests, results)