# -*- mode: python -*-
# -*- coding: utf-8 -*-

##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2024 Emmanuel Viennet.  All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#   Emmanuel Viennet      emmanuel.viennet@gmail.com
#
##############################################################################

"""Gestion évaluations (ScoDoc7, code en voie de modernisation)
"""

import flask
from flask import url_for, g
from flask_login import current_user

from app import db, log

from app.models import Evaluation
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc.sco_exceptions import AccessDenied

from app.scodoc import sco_cache


# ancien _notes_getall
def do_evaluation_get_all_notes(
    evaluation_id, table="notes_notes", filter_suppressed=True, by_uid=None
):
    """Toutes les notes pour une évaluation: { etudid : { 'value' : value, 'date' : date ... }}
    Attention: inclut aussi les notes des étudiants qui ne sont plus inscrits au module.
    """
    # pas de cache pour (rares) appels via undo_notes ou specifiant un enseignant
    do_cache = filter_suppressed and table == "notes_notes" and (by_uid is None)
    if do_cache:
        r = sco_cache.EvaluationCache.get(evaluation_id)
        if r is not None:
            return r
    cnx = ndb.GetDBConnexion()
    cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
    cond = " where evaluation_id=%(evaluation_id)s"
    if by_uid:
        cond += " and uid=%(by_uid)s"

    cursor.execute(
        "select * from " + table + cond,
        {"evaluation_id": evaluation_id, "by_uid": by_uid},
    )
    res = cursor.dictfetchall()
    d = {}
    if filter_suppressed:
        for x in res:
            if x["value"] != scu.NOTES_SUPPRESS:
                d[x["etudid"]] = x
    else:
        for x in res:
            d[x["etudid"]] = x
    if do_cache:
        status = sco_cache.EvaluationCache.set(evaluation_id, d)
        if not status:
            log(f"Warning: EvaluationCache.set: {evaluation_id}\t{status}")
    return d


def moduleimpl_evaluation_move(evaluation_id: int, after=0):
    """Move before/after previous one (decrement/increment numero)
    (published)
    """
    evaluation = Evaluation.get_evaluation(evaluation_id)
    # access: can change eval ?
    if not evaluation.moduleimpl.can_edit_evaluation(current_user):
        raise AccessDenied(
            f"Modification évaluation impossible pour {current_user.get_nomplogin()}"
        )
    after = int(after)  # 0: deplace avant, 1 deplace apres
    if after not in (0, 1):
        raise ValueError('invalid value for "after"')

    Evaluation.moduleimpl_evaluation_renumber(
        evaluation.moduleimpl, only_if_unumbered=True
    )
    mod_evaluations = evaluation.moduleimpl.evaluations.all()
    if len(mod_evaluations) > 1:
        idx = [e.id for e in mod_evaluations].index(evaluation.id)
        neigh = None  # object to swap with
        if after == 0 and idx > 0:
            neigh = mod_evaluations[idx - 1]
        elif after == 1 and idx < len(mod_evaluations) - 1:
            neigh = mod_evaluations[idx + 1]
        if neigh:  #
            if neigh.numero == evaluation.numero:
                log("Warning: moduleimpl_evaluation_move: forcing renumber")
                Evaluation.moduleimpl_evaluation_renumber(
                    evaluation.moduleimpl, only_if_unumbered=False
                )
            else:
                # swap numero with neighbor
                evaluation.numero, neigh.numero = neigh.numero, evaluation.numero
                db.session.add(evaluation)
                db.session.add(neigh)
                db.session.commit()
    # redirect to moduleimpl page:
    return flask.redirect(
        url_for(
            "notes.moduleimpl_status",
            scodoc_dept=g.scodoc_dept,
            moduleimpl_id=evaluation.moduleimpl.id,
        )
    )
