<?php
/**
 * Override standard base class for quiz_overview_report.
 *
 * @package    block_ned_teacher_tools
 * @subpackage NED
 * @copyright  2020 NED {@link http://ned.ca}
 * @author     NED {@link http://ned.ca}
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

namespace block_ned_teacher_tools;
defined('MOODLE_INTERNAL') || die();
/** @var \stdClass $CFG */
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
require_once($CFG->dirroot . '/mod/quiz/report/default.php');
require_once($CFG->dirroot . '/mod/quiz/report/overview/report.php');
require_once($CFG->dirroot . '/mod/quiz/attemptlib.php');
require_once($CFG->dirroot . '/question/engine/lib.php');

class quiz_overview_report extends \quiz_overview_report{

    /**
     * This is a helper used by {@link regrade_attempts()} and
     * {@link regrade_attempts_needing_it()}.
     *
     * Given an array of attempts, it regrades them all, or does a dry run.
     * Each object in the attempts array must be a row from the quiz_attempts
     * table, with the get_all_user_name_fields from the user table joined in.
     * In addition, if $attempt->regradeonlyslots is set, then only those slots
     * are regraded, otherwise all slots are regraded.
     *
     * @param object $quiz the quiz settings.
     * @param array $attempts of data from the quiz_attempts table, with extra data as above.
     * @param bool $dryrun if true, do a pretend regrade, otherwise do it for real.
     * @param \core\dml\sql_join $groupstudentsjoins empty for all attempts, otherwise regrade attempts
     */
    protected function regrade_batch_of_attempts($quiz, array $attempts,
        bool $dryrun, \core\dml\sql_join $groupstudentsjoins) {
        $this->clear_regrade_table($quiz, $groupstudentsjoins);

        $progressbar = new \progress_bar('quiz_overview_regrade_'.$quiz->id, 500, true);
        $a = array(
            'count' => count($attempts),
            'done'  => 0,
        );
        foreach ($attempts as $attempt) {
            $a['done']++;
            $a['attemptnum'] = $attempt->attempt;
            $a['name'] = fullname($attempt);
            $a['attemptid'] = $attempt->id;
            if (!isset($attempt->regradeonlyslots)) {
                $attempt->regradeonlyslots = null;
            }
            $progressbar->update($a['done'], $a['count'],
                get_string('regradingattemptxofywithdetails', 'quiz_overview', $a));
            $this->regrade_attempt($attempt, $dryrun, $attempt->regradeonlyslots);
        }
        $progressbar->update($a['done'], $a['count'],
            get_string('regradedsuccessfullyxofy', 'quiz_overview', $a));

        if (!$dryrun) {
            $this->update_overall_grades($quiz);
        }
    }

    /* NEW FUNCTIONS */

    /**
     * Regrade grades by quiz
     *
     * @param \stdClass     $quiz
     * @param \stdClass|int $cm
     *
     */
    public function ned_regrade($quiz=null, $cm=null){
        global $DB;
        if (!$quiz){
            if(!is_object($cm)){
                if(!$cm = get_coursemodule_from_id('quiz', $cm)){
                    print_error('invalidcoursemodule');
                }
            }
            if(!$course = $DB->get_record('course', array('id' => $cm->course))){
                print_error('coursemisconf');
            }
            if(!$quiz = $DB->get_record('quiz', array('id' => $cm->instance))){
                print_error('invalidcoursemodule');
            }
            $cmid = $cm->id;
        } elseif (!$cm){
            if (isset($quiz->cmid) || isset($quiz->coursemodule)){
                $cmid = $quiz->cmid ?? $quiz->coursemodule;
            } else {
                if (!$course = $DB->get_record('course', array('id' => $quiz->course))) {
                    print_error('invalidcourseid');
                }
                if (!$cm = get_coursemodule_from_instance("quiz", $quiz->id, $course->id)) {
                    print_error('invalidcoursemodule');
                }
                $cmid = $cm->id;
            }
        } else {
            $cmid = is_object($cm) ? $cm->id : $cm;
        }

        $this->context = \context_module::instance($cmid);
        $allowedjoins = new \core\dml\sql_join();
        $this->regrade_attempts($quiz, false, $allowedjoins);
    }

    /**
     *
     * @param \stdClass $course
     * @param bool      $print
     *
     */
    static public function regrade_all_quizzes_by_course($course, $print=false){
        global $OUTPUT;
        $p = function($text, $h=0) use ($print){
            if (!$print){
                return;
            }
            if(!NO_OUTPUT_BUFFERING){
                ob_flush();
                flush();
            }
            if ($h){
                echo \html_writer::tag('h'.$h, $text);
            } else {
                echo \html_writer::div($text);
            }
        };

        if (!$quizzes = get_all_instances_in_course('quiz', $course)) {
            $p($OUTPUT->box(get_string('thereareno', 'moodle',
                get_string('modulenameplural', 'quiz')), 'generalbox', 'notice'));
            return;
        }

        $i=1;
        $max_i = count($quizzes);
        $p(str('quizzestoregrade', $max_i));
        foreach ($quizzes as $quiz){
            $p("$i/$max_i) $quiz->name", 4);
            $qor = new static();
            $qor->ned_regrade($quiz, null);
            $i++;
        }
    }
}