<?php
/**
 * @package    gradingform_kica
 * @category   NED
 * @copyright  2021 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 gradingform_kica;

use \gradingform_kica\shared_lib as NED;
use gradingform_kica_controller;

defined('MOODLE_INTERNAL') || die();

global $CFG;
include_once($CFG->dirroot . '/lib/grouplib.php');

/**
 * Class data
 *
 * @package gradingform_kica
 */
class data {
    /**
     * @var
     */
    private $cm;
    /**
     * @var
     */
    private $includeallattampts;
    /**
     * @var
     */
    private $includeinactivestudents;

    /**
     * @param $cm
     * @param $includeallattampts
     */
    public function __construct($cm, $includeallattampts, $includeinactivestudents) {
        $this->cm = $cm;
        $this->includeallattampts = $includeallattampts;
        $this->includeinactivestudents = $includeinactivestudents;
    }

    /**
     * @return array
     */
    public static function get_export_actions() {
        return [
            gradingform_kica_controller::EXPORT_STUDENT,
            gradingform_kica_controller::EXPORT_CLASS,
            gradingform_kica_controller::EXPORT_COURSE,
            gradingform_kica_controller::EXPORT_GT
        ];
    }

    /**
     * @return array[]
     * @throws \coding_exception
     */
    public static function get_export_options() {
        return [
            ['id' => gradingform_kica_controller::EXPORT_STUDENT, 'name' => get_string(gradingform_kica_controller::EXPORT_STUDENT, 'gradingform_kica')],
            ['id' => gradingform_kica_controller::EXPORT_CLASS, 'name' => get_string(gradingform_kica_controller::EXPORT_CLASS, 'gradingform_kica')],
            ['id' => gradingform_kica_controller::EXPORT_COURSE, 'name' => get_string(gradingform_kica_controller::EXPORT_COURSE, 'gradingform_kica')],
            ['id' => gradingform_kica_controller::EXPORT_GT, 'name' => get_string(gradingform_kica_controller::EXPORT_GT, 'gradingform_kica')],
        ];
    }

    /**
     * @param $userid
     * @return array
     * @throws \dml_exception
     */
    public function get_user_data($userid) {
        global $DB;

        $includeallattampts = '';
        if (!$this->includeallattampts) {
            $includeallattampts = ' AND asub.latest';
        }

        $sql = "SELECT grf.id as grfid,
                       asg.grade as gradeoutof,
                       crit.id critid,
			           crit.category criteriacategory,
			           crit.description creterianame,
			           crit.score maxscore,
			           level.score level,
			           grf.grade grade,
			           level.definition,
			           grf.remark,
			           grf.criterionid,
			           ag.userid, 
			           g.usermodified raterid,
			           gin.timemodified AS modified,
			           ag.grade assigngrade,
			           ag.attemptnumber,
			           gin.id instanceid
				  FROM {assign} asg
				  JOIN {course_modules} cm ON cm.instance = asg.id
				  JOIN {context} ctx ON ctx.instanceid = cm.id
				  JOIN {grading_areas} ga ON ctx.id=ga.contextid
				  JOIN {grading_definitions} gd ON ga.id = gd.areaid
				  JOIN {gradingform_kica_criteria} crit ON crit.definitionid = gd.id
				  JOIN {gradingform_kica_levels} level ON level.criterionid = crit.id
				  JOIN {grading_instances} gin ON gin.definitionid = gd.id
				  JOIN {assign_grades} ag ON ag.id = gin.itemid
    			  JOIN {assign_submission} asub ON ag.assignment = asub.assignment AND ag.userid = asub.userid  AND ag.attemptnumber = asub.attemptnumber
				  JOIN {gradingform_kica_fillings} grf ON (grf.instanceid = gin.id) AND (grf.criterionid = crit.id) AND (grf.levelid = level.id)
                  JOIN {grade_grades} g ON g.userid = ag.userid
				  JOIN {grade_items} gi ON g.itemid = gi.id AND gi.itemtype = 'mod' AND gi.itemmodule = 'assign' AND gi.iteminstance = ?
		         WHERE cm.id = ? 
		           AND ag.userid = ?
  	               AND gin.status = ?
		               {$includeallattampts}
		      ORDER BY ag.attemptnumber ASC, crit.sortorder ASC";
        $attemptgrades = [];

        if ($data = $DB->get_records_sql($sql, [$this->cm->instance, $this->cm->id, $userid, \gradingform_instance::INSTANCE_STATUS_ACTIVE])) {
            foreach ($data as $datum) {
                $attemptgrades[$datum->attemptnumber][$datum->critid] = $datum;
            }
        }

        return $attemptgrades;
    }

    /**
     * @param $graderid
     * @return array
     * @throws \dml_exception
     */
    public function get_graded_user_ids($graderid = false) {
        global $DB;

        $params = [];
        $params['cmid'] = $this->cm->id;
        $params['iteminstance'] = $this->cm->instance;
        $params['status'] = \gradingform_instance::INSTANCE_STATUS_ACTIVE;
        $gradersql = '';

        if ($graderid) {
            $gradersql = ' AND g.usermodified = :raterid';
            $params['raterid'] = $graderid;
        }

        $sql = "SELECT DISTINCT ag.userid
				  FROM {assign} asg
				  JOIN {course_modules} cm ON cm.instance = asg.id
				  JOIN {context} ctx ON ctx.instanceid = cm.id
				  JOIN {grading_areas} ga ON ctx.id=ga.contextid
				  JOIN {grading_definitions} gd ON ga.id = gd.areaid
				  JOIN {gradingform_kica_criteria} crit ON (crit.definitionid = gd.id)
				  JOIN {gradingform_kica_levels} level ON (level.criterionid = crit.id)
				  JOIN {grading_instances} gin ON gin.definitionid = gd.id
				  JOIN {assign}_grades ag ON ag.id = gin.itemid
				  JOIN {gradingform_kica_fillings} grf ON grf.instanceid = gin.id AND grf.criterionid = crit.id AND grf.levelid = level.id
				  JOIN {grade_grades} g ON g.userid = ag.userid
				  JOIN {grade_items} gi ON g.itemid = gi.id AND gi.itemtype = 'mod' AND gi.itemmodule = 'assign' AND gi.iteminstance = :iteminstance
		         WHERE cm.id = :cmid AND gin.status = :status
		               $gradersql";

        $users = $this->get_course_users();
        $gtusers =  $DB->get_records_sql($sql, $params);

        if (empty($users) || empty($gtusers)) {
            return null;
        }

        return array_intersect_key($users, $gtusers);
    }

    /**
     * @return array
     * @throws \dml_exception
     */
    public function get_creteria() {
        global $DB;

        $sql = "SELECT crit.*
				  FROM {assign} asg
				  JOIN {course_modules} cm ON cm.instance = asg.id
				  JOIN {context} ctx ON ctx.instanceid = cm.id
				  JOIN {grading_areas} ga ON ctx.id=ga.contextid
				  JOIN {grading_definitions} gd ON ga.id = gd.areaid
				  JOIN {gradingform_kica_criteria} crit ON (crit.definitionid = gd.id)
		         WHERE cm.id = ? 
		      ORDER BY crit.sortorder ASC";

        return $DB->get_records_sql($sql, [$this->cm->id]);
    }

    /**
     * @param $gradingisntanceid
     * @param $rater
     * @return null
     * @throws \dml_exception
     */
    public function get_user_id($gradingisntanceid, $rater = false) {
        global $DB;

        $sql = "SELECT DISTINCT ag.userid, g.usermodified raterid
				  FROM {assign} asg
				  JOIN {course_modules} cm ON cm.instance = asg.id
				  JOIN {context} ctx ON ctx.instanceid = cm.id
				  JOIN {grading_areas} ga ON ctx.id=ga.contextid
				  JOIN {grading_definitions} gd ON ga.id = gd.areaid
				  JOIN {gradingform_kica_criteria} crit ON (crit.definitionid = gd.id)
				  JOIN {gradingform_kica_levels} level ON (level.criterionid = crit.id)
				  JOIN {grading_instances} gin ON gin.definitionid = gd.id
				  JOIN {assign_grades} ag ON ag.id = gin.itemid
                  JOIN {grade_grades} g ON g.userid = ag.userid
				  JOIN {grade_items} gi ON g.itemid = gi.id AND gi.itemtype = 'mod' AND gi.itemmodule = 'assign' AND gi.iteminstance = ?
		         WHERE cm.id = ? AND gin.id = ?";

        $user = $DB->get_record_sql($sql, [$this->cm->instance, $this->cm->id, $gradingisntanceid]);

        if ($rater) {
            return $user->raterid ?? null;
        }
        return $user->userid ?? null;
    }

    /**
     * @param $userid
     * @return mixed|\stdClass|null
     */
    public function get_group($userid) {
        $group = null;
        $groupings = NED::get_user_groupids($this->cm->course, $userid);
        if (!empty($groupings)){
            $group = NED::get_group(reset($groupings));
        }

        return $group;
    }

    /**
     * @param $group
     * @return array|int[]|object[]|null
     */
    public function get_group_users($group) {
        $users = $this->get_course_users();
        $groupusers = NED::get_group_users($group->id, false);

        if (empty($users) || empty($groupusers)) {
            return null;
        }
        return array_intersect_key($users, $groupusers);
    }

    /**
     * @return array
     */
    public function get_course_users() {
        $coursecontext = \context_course::instance($this->cm->course);
        return get_enrolled_users($coursecontext, 'mod/assign:submit', 0, 'u.*', 'u.id', 0, 0, !$this->includeinactivestudents);
    }

    /**
     * @param $userid
     * @return \local_schoolmanager\school
     */
    public function get_school($userid) {
        if ($schoolid = NED::get_user_school($userid, true)) {
            $school = new \local_schoolmanager\school($schoolid);
        }

        return $school ?? null;
    }

    /**
     * @param $userid
     * @param $attemptnumber
     * @return false|mixed
     * @throws \dml_exception
     */
    public function get_final_comment($userid, $attemptnumber) {
        global $DB;

        $sql = "SELECT f.commenttext
                  FROM {assign_grades} g
                  JOIN {assignfeedback_comments} f 
                    ON g.id = f.grade
                 WHERE g.assignment = ? AND g.userid = ? AND g.attemptnumber = ?";

        return $DB->get_field_sql($sql, [$this->cm->instance, $userid, $attemptnumber]);
    }
}