<?php

namespace local_treestudyplan;
require_once($CFG->libdir.'/externallib.php');
require_once($CFG->libdir.'/gradelib.php');
require_once($CFG->dirroot.'/course/lib.php');

use core_course\local\repository\caching_content_item_readonly_repository;
use core_course\local\repository\content_item_readonly_repository;
use \grade_item;
use \grade_scale;
use \grade_outcome;

class courseinfo {
    const TABLE = 'course';
    
    private $course;
    private $context;
    private $coursecontext;
    private $studyitem;
    private static $contentitems = null;

    public function id(){
        return $this->course->id;
    }

    public function shortname(){
        return $this->course->shortname;
    }

    public function course(){
        return $this->course; // php arrays are assigned by copy
    }

    public function course_context(){
        return $this->coursecontext;
    }

    public function category_context(){
        return $this->context;
    }

    protected function get_contentitems() {
        global $PAGE;
        if(empty(static::$contentitems)){
            $PAGE->set_context(\context_system::instance());
            static::$contentitems = (new content_item_readonly_repository())->find_all();
        }
        return static::$contentitems;
    }

    protected function amTeacher(){
        global $USER;
        return is_enrolled($this->coursecontext, $USER, 'mod/assign:grade');
    }

    protected function iCanSelectGradables($userid=-1){
        global $USER, $DB;
        if($userid <= 0){
            $usr = $USER;
        }
        else 
        {
            $usr = $DB->get_record('user', ['id' => $userid, 'deleted' => 0]);
        }
        return($usr && is_enrolled($this->coursecontext, $usr, 'local/treestudyplan:selectowngradables'));
    }    

    public static function get_contentitem($name) {
        $contentitems = static::get_contentitems();
        for($i = 0; $i < count($contentitems); $i++){
            if($contentitems[$i]->get_name() == $name){
                return $contentitems[$i];
            }
        }
        return null;     
    }

    public function __construct($id,studyitem $studyitem = null){
        global $DB;
        $this->studyitem = $studyitem;
        $this->course = \get_course($id);
        $this->context = \context_coursecat::instance($this->course->category);
        $this->coursecontext = \context_course::instance($this->course->id);
    }

    public static function exists($id){
        global $DB;
        return is_numeric($id) && $DB->record_exists(self::TABLE, ['id' => $id]);
    }

    public static function id_from_shortname($shortname){
        global $DB;
        
        return $DB->get_field(self::TABLE, "id", ['shortname' => $shortname]);
    }

    public static function coursetiming($course){
        $now = time();
        if($now > $course->startdate)
        {
            if($course->enddate > 0 && $now > $course->enddate)
            {
                return "past";
            }		
            else {
                return "present";
            }
        } 
        else{ 
            return "future";
        }
    }

    public function timing(){
        return self::coursetiming($this->course);
    }
    
    public function displayname(){
        $displayfield = get_config("local_treestudyplan","display_field");
        if ($displayfield == "idnumber") {
            $idnumber = trim(preg_replace("/\s+/u", " ",$this->course->idnumber));
            if(strlen($idnumber) > 0){
                return $this->course->idnumber;
            }
        } else if(strpos( $displayfield ,"customfield_") === 0) {
            $fieldname = substr($displayfield,strlen("customfield_"));
            
            $handler = \core_customfield\handler::get_handler('core_course', 'course');
            $datas = $handler->get_instance_data($this->course->id);
            foreach($datas as $data){
                if($data->get_field()->get('shortname') == $fieldname){
                    $value = trim(preg_replace("/\s+/u", " ",$data->get_value()));
                    if(strlen($value) > 0){
                        return $value;
                    }
                }
            }
        }
        // Fallback to shortname when the specified display field fails, since shortname is never empty
        return $this->course->shortname;
    }

    public static function simple_structure($value=VALUE_REQUIRED){
        return new \external_single_structure([
            "id" => new \external_value(PARAM_INT, 'linked course id'),
            "fullname" => new \external_value(PARAM_TEXT, 'linked course name'),
            "shortname" => new \external_value(PARAM_TEXT, 'linked course shortname'),
            "displayname" => new \external_value(PARAM_TEXT, 'linked course displayname'),
            "context" => contextinfo::structure(VALUE_OPTIONAL),
        ], 'referenced course information',$value);
    }

    public function simple_model() {
        $contextinfo = new contextinfo($this->context);
        $info = [
            'id' => $this->course->id,
            'fullname' => $this->course->fullname,
            'shortname' => $this->course->shortname,
            'displayname' => $this->displayname(),
            'context' => $contextinfo->model()
        ];
        
        return $info;
    }

    public static function editor_structure($value=VALUE_REQUIRED){
        return new \external_single_structure([
            "id" => new \external_value(PARAM_INT, 'linked course id'),
            "fullname" => new \external_value(PARAM_TEXT, 'linked course name'),
            "shortname" => new \external_value(PARAM_TEXT, 'linked course shortname'),
            "displayname" => new \external_value(PARAM_TEXT, 'linked course displayname'),
            "context" => contextinfo::structure(VALUE_OPTIONAL),
            "ctxid" => new \external_value(PARAM_INT, 'course context id name'),
            "grades" => new \external_multiple_structure(gradeinfo::editor_structure(),'grade list (legacy list)',VALUE_OPTIONAL),
            "completion" => corecompletioninfo::editor_structure(VALUE_OPTIONAL),
            "timing" => new \external_value(PARAM_TEXT, '(past|present|future)'),
            "startdate" => new \external_value(PARAM_TEXT, 'Course start date'),
            "enddate" => new \external_value(PARAM_TEXT, 'Course end date'),
            "amteacher" => new \external_value(PARAM_BOOL, 'Requesting user is teacher in this course'),
            "canupdatecourse" => new \external_value(PARAM_BOOL, "If the current user can update this course"),
            "canselectgradables" => new \external_value(PARAM_BOOL, 'Requesting user can change selected gradables'),
            "tag" => new \external_value(PARAM_TEXT, 'Tag'),
        ], 'referenced course information',$value);
    }

    public function editor_model(studyitem $studyitem=null, $usecorecompletioninfo=false) {
        global $DB;
        $contextinfo = new contextinfo($this->context);
        
        $timing = $this->timing();
        
        $info = [
            'id' => $this->course->id,
            'fullname' => $this->course->fullname,
            'shortname' => $this->course->shortname,
            'displayname' => $this->displayname(),
            'context' => $contextinfo->model(),
            'ctxid' => $this->coursecontext->id,
            'timing' => $timing,
            'startdate' => date("Y-m-d",$this->course->startdate,), 
            'enddate' => date("Y-m-d",$this->course->enddate),            
            'amteacher' => $this->amTeacher(),
            'canupdatecourse' => \has_capability("moodle/course:update",$this->coursecontext),
            'canselectgradables' =>  $this->iCanSelectGradables(),
            'tag' => "Editormodel",
            'grades' => [],
        ];
        
        if(!$usecorecompletioninfo){
            $gradables = gradeinfo::list_course_gradables($this->course,$studyitem);
            
            foreach($gradables as $gradable) {
                $info['grades'][] = $gradable->editor_model($studyitem);
            }
        }
        else {
            $cc = new corecompletioninfo($this->course);
            $info['completion'] = $cc->editor_model();
        }

        return $info;
    }

    public static function user_structure($value=VALUE_REQUIRED){
        return new \external_single_structure([
            "id" => new \external_value(PARAM_INT, 'linked course id'),
            "fullname" => new \external_value(PARAM_TEXT, 'linked course name'),
            "shortname" => new \external_value(PARAM_TEXT, 'linked course shortname'),
            "displayname" => new \external_value(PARAM_TEXT, 'linked course displayname'),
            "context" => contextinfo::structure(VALUE_OPTIONAL),
            "ctxid" => new \external_value(PARAM_INT, 'course context id name'),
            "grades" => new \external_multiple_structure(gradeinfo::user_structure(),'grade list (legacy list)',VALUE_OPTIONAL),
            "completion" => corecompletioninfo::user_structure(VALUE_OPTIONAL),            
            "timing" => new \external_value(PARAM_TEXT, '(past|present|future)'),
            "startdate" => new \external_value(PARAM_TEXT, 'Course start date'),
            "enddate" => new \external_value(PARAM_TEXT, 'Course end date'),
        ], 'course information',$value);
    }

    public function user_model($userid,$usecorecompletioninfo=false) {
        global $DB;
        $contextinfo = new contextinfo($this->context);

        $timing = $this->timing();

        $info = [
            'id' => $this->course->id,
            'fullname' => $this->course->fullname,
            'shortname' => $this->course->shortname,
            'displayname' => $this->displayname(),
            'context' => $contextinfo->model(),
            'ctxid' => $this->coursecontext->id,
            'timing' => $timing,
            'startdate' => date("Y-m-d",$this->course->startdate), 
            'enddate' => date("Y-m-d",$this->course->enddate),
            'grades' => [],
        ];

        if(!$usecorecompletioninfo){
            $gradables = gradeinfo::list_studyitem_gradables($this->studyitem);
            foreach($gradables as $gi) {
                $info['grades'][] = $gi->user_model($userid);
            }
        }
        else {
            $cc = new corecompletioninfo($this->course);
            $info['completion'] = $cc->user_model($userid);
        }



        return $info;
    }

}
