<?php

namespace local_treestudyplan\form;

use local_treestudyplan\aggregator;
use local_treestudyplan\studyplan;
use local_treestudyplan\studyplanpage;
use local_treestudyplan\courseservice;
use local_treestudyplan\form\text_integer;
use local_treestudyplan\local\helpers\webservicehelper;
use local_treestudyplan\studyplanservice;
use moodle_exception;
use stdClass;

/**
 * Moodleform class for the studyplan editor. A Moodleform is used here to facilitate a rich editor 
 * in the studyplan description 
 */
class studyplanpage_editform extends formbase {
    /**
     * Capability required to edit study plans
     * @var string
     */
    const CAP_EDIT = "local/treestudyplan:editstudyplan";

    /**
     * Translate parameters into customdata. 
     * 
     * @param object $params The parameters for form initialization
     * @return array Form data based on parameters
     */    
    public static function init_customdata(object $params) {
        $customdata = new stdClass;
        $customdata->create = $params->mode=='create'?true:false;
        if($customdata->create){
            $customdata->plan = studyplan::find_by_id($params->studyplan_id);
        } else {
            $customdata->page = studyplanpage::find_by_id($params->page_id);
            $customdata->plan = $customdata->page->studyplan();
            $customdata->simplemodel = $customdata->page->simple_model();
        }
        $customdata->context = $customdata->plan->context();

        $customdata->editoroptions = [
            'trusttext' => true,
            'subdirs' => true,
            'maxfiles' => 20,
            'maxbytes' => 20*1024*1024,
            'context' => \context_system::instance(), // Keep the files in system context
        ];
        $customdata->fileoptions = [
            'subdirs' => 0,
            'maxbytes' => 10*1024*1024, // Max 10MiB should be sufficient for a picture.
            'areamaxbytes' => 10485760,
            'maxfiles' => 1, // Just one file
            'accepted_types' => ['.jpg', '.png'],
            'return_types' => FILE_INTERNAL | FILE_EXTERNAL,
        ];
        return $customdata; 
    }

    /**
     * Validate security access for this form based on the customdata generated by init_customdata
     * Return true if validation passes, false or throw an exception if it does not.
     * 
     * @param object $customdata The customdata for this form
     * @return bool True if security validation passes. 
     * @throws \moodle_exception if access denied for a specific reason.
     */
    public static function check_security(object $customdata) {
        /*webservicehelper::require_capabilities(self::CAP_EDIT,$customdata->context); */
    }

    /**
     * Generate form data from parameters
     * Also validate parameters and access permissions here
     * 
     * @param object $customdata The parameters for form initialization
     * @return array Form data based on parameters
     */    
    public function init_formdata(object $customdata) {
        global $DB;
        /*  Use direct database retrieval to avoid our abstractions causing trouble
            with existing moodle code assumptions. 
            The form API does seem needlessly convoluted in it's use, but we need the editor...
        */
        if($customdata->create) {
            $plan = $customdata->plan;
            $entry = new stdClass;
            $entry->studyplan_id = $plan->id();

            // By default, make the start date of a new page, continue 1 day after the last page's start date;
            $otherpages = $plan->pages();
            if(count($otherpages) > 0){
                $lastpage = $otherpages[count($otherpages) -1];

                // Propose 1 year after the last page's start date, if no end date is set.
                if ($lastpage->enddate(false) == null) {
                    $entry->startdate = $lastpage->startdate()->add(new \DateInterval("P1Y"))->format("U");
                } else {
                    // Otherwise, propose 1 day after the last page's end date
                    $entry->startdate = $lastpage->enddate()->add(new \DateInterval("P1D"))->format("U");
                }

            } else {
                // Determine the next august 1st for default value purposes. Only if no other page is available
                $august = strtotime("first day of august this year");
                if($august < time()) {
                    $august = strtotime("first day of august next year");
                }
            
                $entry->startdate = $august;

            }
            $entry->enddate = $entry->startdate + (364*24*60*60); // Not bothering about leap years here.
            $entry->periods = 4;
        } else {
            $entry = $DB->get_record(studyplanpage::TABLE, ['id' => $customdata->page->id()]);
            $entry->startdate = strtotime($entry->startdate);
            $entry->enddate = strtotime($entry->enddate);
        }

        // Prepare the editor
        $entry = file_prepare_standard_editor(  $entry,
            'description',
            $customdata->editoroptions,
            \context_system::instance(),
            'local_treestudyplan',
            'studyplanpage',
            ($customdata->create)?null:$customdata->page->id()
        );

        return $entry;

    }

    /**
     * Set up the form definition
     */
    public function definition() {
        $mform = $this->_form;
        $customdata = (object)$this->_customdata;

        // Register integer type
        text_integer::Register();

        // Define the form
        $field = 'fullname';
        $mform->addElement('text',$field,
            get_string('studyplan_name','local_treestudyplan'),
            []);
        $mform->addRule($field, null, 'required', null, 'client');

        $field = 'shortname';
        $mform->addElement('text',$field,
            get_string('studyplan_shortname','local_treestudyplan'),
            []);
        $mform->addRule($field, null, 'required', null, 'client');

        $field = 'startdate';
        $mform->addElement('date_selector',$field,
            get_string('studyplan_startdate','local_treestudyplan'),
            []);
        $mform->addRule($field, null, 'required', null, 'client');

        $field = 'enddate';
        $mform->addElement('date_selector',$field,
            get_string('studyplan_startdate','local_treestudyplan'),
            []);
        $mform->addRule($field, null, 'required', null, 'client');

        $field = 'periods';
        $mform->addElement('text_integer',$field,
            get_string('studyplan_slots','local_treestudyplan'),
            ["unsigned" => true, "nonzero" => true]);
        $mform->setType($field, PARAM_INT);
        $mform->addRule($field, null, 'required', null, 'client');

        $field = 'description_editor';
        $mform->addElement('editor', $field,
             get_string('studyplan_description', 'local_treestudyplan'), 
             null, 
             $customdata->editoroptions);
        $mform->setType($field, PARAM_RAW);

    }

    /** 
     * Process the submitted data and perform necessary actions
     * @param object $entry The processed form data;
     * @return bool false if submission not successful
     * @throws \moodle_exception if an error must be given for a specific reason.
     */
    protected function process_submitted_data($entry) {
        $customdata = (object)$this->_customdata;

        if($customdata->create) {

            // Use our own abstraction to update the record, so caches are maintained
            $page = studyplanpage::add(['fullname' => $entry->fullname,
                                    'shortname' => $entry->shortname,
                                    'startdate' => date("Y-m-d",$entry->startdate),
                                    'enddate' => date("Y-m-d",$entry->enddate),
                                    'periods' => $entry->periods,
                                    'studyplan_id' => $customdata->plan->id(),
                                    ]);
            // Process the provided files in the description editor
            $entry = file_postupdate_standard_editor($entry,
                                                    'description',
                                                    $customdata->editoroptions,
                                                    \context_system::instance(),
                                                    'local_treestudyplan',
                                                    'studyplan',
                                                    $page->id());   
            // Update the description
            $page->edit([
                'description' => $entry->description,
                'descriptionformat' => $entry->descriptionformat,
            ]);
        } else {
            $page = $customdata->page;
            
            // Process the provided files in the description editor
            $entry = file_postupdate_standard_editor($entry,
                                                    'description',
                                                    $customdata->editoroptions,
                                                    \context_system::instance(),
                                                    'local_treestudyplan',
                                                    'studyplanpage',
                                                    $page->id());

            // Use our own abstraction to update the record, so caches are maintained
            $page->edit(['fullname' => $entry->fullname,
                        'shortname' => $entry->shortname,
                        'description' => $entry->description,
                        'descriptionformat' => $entry->descriptionformat,
                        'startdate' => date("Y-m-d",$entry->startdate),
                        'enddate' => date("Y-m-d",$entry->enddate),
                        'periods' => $entry->periods,
                        ]);
        }

        /* Return the editor structure of the new / edited page
           Parse it through the clean_returnvalue function of exernal api (of which studyplanservice is a subclass)
           so we return it in a consistent way 
        */
        return studyplanservice::clean_returnvalue(studyplanpage::editor_structure(),$page->editor_model());
    }


}