<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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 3 of the License, or
// (at your option) any later version.
//
// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * @package    format_ned
 * @subpackage NED
 * @copyright  NED {@link http://ned.ca}
 * @author     NED {@link http://ned.ca}
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @developer  G J Barnard - {@link http://about.me/gjbarnard} and
 *                           {@link http://moodle.org/user/profile.php?id=442195}
 */

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

/**
 * All upgrades checks from Moodle 3
 *
 * @param int $oldversion
 */
function format_ned_upgrade_moodle3_upgrades($oldversion): void{
    global $DB;
    $dbman = $DB->get_manager();

    if ($oldversion < 2017061900) {
        // Remove 'numsections' option and hide or delete orphaned sections.
        format_ned_upgrade_remove_numsections();

        upgrade_plugin_savepoint(true, 2017061900, 'format', 'ned');
    }

    if ($oldversion < 2017061903) {
        // Define table format_ned_colour to be created.
        $table = new xmldb_table('format_ned_colour');

        // Adding fields to table format_ned_colour.
        $table->add_field('id', XMLDB_TYPE_INTEGER, '18', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, '');
        $table->add_field('framedsectionbgcolour', XMLDB_TYPE_CHAR, '255', null, null, null, null);
        $table->add_field('framedsectionheadertxtcolour', XMLDB_TYPE_CHAR, '255', null, null, null, null);
        $table->add_field('predefined', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
        $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '11', null, XMLDB_NOTNULL, null, '0');
        $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '11', null, XMLDB_NOTNULL, null, '0');

        // Adding keys to table format_ned_colour.
        $table->add_key('id', XMLDB_KEY_PRIMARY, array('id'));

        // Conditionally launch create table for format_ned_colour.
        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);

            $recone = new stdClass();
            $rectwo = new stdClass();
            $recone->name = 'Embassy Green';
            $rectwo->name = 'Blues on Whyte';
            $recone->framedsectionbgcolour = '9DBB61';
            $rectwo->framedsectionbgcolour = '7CAAFE';
            $recone->framedsectionheadertxtcolour = 'FFFFFF';
            $rectwo->framedsectionheadertxtcolour = 'FFFFFF';
            $recone->predefined = 1;
            $rectwo->predefined = 1;
            $recone->timecreated = time();
            $rectwo->timecreated = time();
            $recone->timemodified = time();
            $rectwo->timemodified = time();

            $DB->insert_record('format_ned_colour', $recone);
            $DB->insert_record('format_ned_colour', $rectwo);
        }
        // NED savepoint reached.
        upgrade_plugin_savepoint(true, 2017061903, 'format', 'ned');
    }

    if ($oldversion < 2017061907) {
        // Define table format_ned_colour.
        $table = new xmldb_table('format_ned_colour');

        $field = new xmldb_field('framedsectionborderwidth', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '3');

        // Conditionally launch add field framedsectionborderwidth.
        if (!$dbman->field_exists($table, $field)) {
            $dbman->add_field($table, $field);
        }

        // NED savepoint reached.
        upgrade_plugin_savepoint(true, 2017061907, 'format', 'ned');
    }

    if ($oldversion < 2017121200) {
        $table = new xmldb_table('format_ned');

        $table->add_field('id', XMLDB_TYPE_INTEGER, '18', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
        $table->add_field('courseid', XMLDB_TYPE_INTEGER, '18', null, XMLDB_NOTNULL, null, null);
        $table->add_field('sectionid', XMLDB_TYPE_INTEGER, '18', null, XMLDB_NOTNULL, null, '0');
        $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, null, null, null);
        $table->add_field('value', XMLDB_TYPE_TEXT, null, null, null, null, null);

        $table->add_key('mdl_courformopti_couforsec_uix', XMLDB_KEY_UNIQUE, array('courseid', 'sectionid', 'name'));
        $table->add_key('id', XMLDB_KEY_PRIMARY, array('id'));

        $table->add_index('mdl_courformopti_cou_ix', XMLDB_INDEX_NOTUNIQUE, array('courseid'));

        if (!$dbman->table_exists($table)) {
            $dbman->create_table($table);
        }

        upgrade_plugin_savepoint(true, 2017121200, 'format', 'ned');
    }

    if ($oldversion < 2018030602) {
        // Define table format_ned_colour.
        $table = new xmldb_table('format_ned_colour');

        // Add 'Grey Skies' if the table exists, which it should.
        if ($dbman->table_exists($table)) {

            $recthree = new stdClass();
            $recthree->name = 'Grey Skies';
            $recthree->framedsectionbgcolour = '999999';
            $recthree->framedsectionheadertxtcolour = 'FFFFFF';
            $recthree->framedsectionborderwidth = 3;
            $recthree->predefined = 1;
            $recthree->timecreated = time();
            $recthree->timemodified = time();

            $DB->insert_record('format_ned_colour', $recthree);
        }
        // NED savepoint reached.
        upgrade_plugin_savepoint(true, 2018030602, 'format', 'ned');
    }

    // Automatic 'Purge all caches'....
    if ($oldversion < 2117101700) {
        purge_all_caches();
    }
}

/**
 * This method finds all courses in 'ned' format that have actual number of sections
 * bigger than their 'numsections' course format option.
 * For each such course we call {@link format_ned_upgrade_hide_extra_sections()} and
 * either delete or hide "orphaned" sections.
 */
function format_ned_upgrade_remove_numsections() {
    global $DB;

    $sql1 = "SELECT c.id, max(cs.section) AS sectionsactual
          FROM {course} c
          JOIN {course_sections} cs ON cs.course = c.id
          WHERE c.format = :format1
          GROUP BY c.id";

    $sql2 = "SELECT c.id, n.value AS numsections
          FROM {course} c
          JOIN {course_format_options} n ON n.courseid = c.id AND n.format = :format1 AND n.name = :numsections AND n.sectionid = 0
          WHERE c.format = :format2";

    $params = ['format1' => 'ned', 'format2' => 'ned', 'numsections' => 'numsections'];

    $actual = $DB->get_records_sql_menu($sql1, $params);
    $numsections = $DB->get_records_sql_menu($sql2, $params);
    $needfixing = [];

    $defaultnumsections = get_config('moodlecourse', 'numsections');

    foreach ($actual as $courseid => $sectionsactual) {
        if (array_key_exists($courseid, $numsections)) {
            $n = (int)$numsections[$courseid];
        } else {
            $n = $defaultnumsections;
        }
        if ($sectionsactual > $n) {
            $needfixing[$courseid] = $n;
        }
    }
    unset($actual);
    unset($numsections);

    foreach ($needfixing as $courseid => $numsections) {
        format_ned_upgrade_hide_extra_sections($courseid, $numsections);
    }

    $DB->delete_records('course_format_options', ['format' => 'ned', 'sectionid' => 0, 'name' => 'numsections']);
}

/**
 * Find all sections in the course with sectionnum bigger than numsections.
 * Either delete these sections or hide them
 *
 * We will only delete a section if it is completely empty and all sections below
 * it are also empty
 *
 * @param int $courseid
 * @param int $numsections
 */
function format_ned_upgrade_hide_extra_sections($courseid, $numsections) {
    global $DB;
    $sections = $DB->get_records_sql('SELECT id, name, summary, sequence, visible
        FROM {course_sections}
        WHERE course = ? AND section > ?
        ORDER BY section DESC', [$courseid, $numsections]);
    $candelete = true;
    $tohide = [];
    $todelete = [];
    foreach ($sections as $section) {
        if ($candelete && (!empty($section->summary) || !empty($section->sequence) || !empty($section->name))) {
            $candelete = false;
        }
        if ($candelete) {
            $todelete[] = $section->id;
        } else if ($section->visible) {
            $tohide[] = $section->id;
        }
    }
    if ($todelete) {
        // Delete empty sections in the end.
        // This is an upgrade script - no events or cache resets are needed.
        // We also know that these sections do not have any modules so it is safe to just delete records in the table.
        $DB->delete_records_list('course_sections', 'id', $todelete);
    }
    if ($tohide) {
        // Hide other orphaned sections.
        // This is different from what set_section_visible() does but we want to preserve actual
        // module visibility in this case.
        list($sql, $params) = $DB->get_in_or_equal($tohide);
        $DB->execute("UPDATE {course_sections} SET visible = 0 WHERE id " . $sql, $params);
    }
}
