<?php
// This file is part of mod_openbook for Moodle - http://moodle.org/
//
// It 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.
//
// It 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/>.

/**
 * Base class for tables showing files related to me (uploaded by me, imported from me or my group and options to approve them)
 *
 * @package       mod_openbook
 * @author        University of Geneva, E-Learning Team
 * @author        Academic Moodle Cooperation {@link http://www.academic-moodle-cooperation.org}
 * @copyright     2025 University of Geneva {@link http://www.unige.ch}
 * @license       http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

namespace mod_openbook\local\filestable;

use core_text;

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

global $CFG;

require_once($CFG->dirroot . '/course/moodleform_mod.php');
require_once($CFG->dirroot . '/mod/openbook/locallib.php');
require_once($CFG->libdir . '/tablelib.php');

/**
 * Base class for tables showing my files or group files (upload or import)
 *
 * @package       mod_openbook
 * @author        University of Geneva, E-Learning Team
 * @author        Academic Moodle Cooperation {@link http://www.academic-moodle-cooperation.org}
 * @copyright     2025 University of Geneva {@link http://www.unige.ch}
 * @license       http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class base extends \html_table {
    /** @var \openbook openbook object */
    protected $openbook = null;
    /** @var \file_storage file storage object */
    protected $fs = null;
    /** @var \stored_file[] array of stored_file objects */
    protected $files = null;
    /** @var \stored_file[] array of stored_file objects used in onlinetexts */
    protected $resources = null;
    /** @var bool whether or not changes of approval are still possible */
    protected $changepossible = false;
    /** @var string[] select options */
    protected $options = [];
    /** @var string valid icon string */
    protected $valid = '';
    /** @var string questionmark icon string */
    protected $questionmark = '';
    /** @var string invalid icon string */
    protected $invalid = '';
    /** @var string share icon string */
    protected $share = '';
    /** @var int timestamp with modification time */
    public $lastmodified = 0;

    /**
     * constructor
     *
     * @param \openbook $openbook openbook object
     */
    public function __construct(\openbook $openbook) {
        global $OUTPUT;

        parent::__construct();

        $this->openbook = $openbook;

        $this->fs = get_file_storage();

        $this->valid = \mod_openbook\local\allfilestable\base::approval_icon('check', 'text-success', false);
        $this->questionmark = \mod_openbook\local\allfilestable\base::approval_icon('question', 'text-warning', false);
        $this->invalid = \mod_openbook\local\allfilestable\base::approval_icon('times', 'text-danger', false);
        $this->share = \mod_openbook\local\allfilestable\base::approval_icon(
            'share-from-square',
            'text-success',
            false
        );
    }

    /**
     * Initialize the table (get the files, style table, prepare options used for approval-selects, add files to table, etc.)
     *
     * @return int amount of files in table
     */
    public function init() {
        $files = $this->get_files();

        if (
            (!$files || count($files) == 0) &&
            has_capability('mod/openbook:upload', $this->openbook->get_context())
        ) {
            return 0;
        }

        if (!isset($this->attributes)) {
            $this->attributes = ['class' => 'coloredrows'];
        } else if (!isset($this->attributes['class'])) {
            $this->attributes['class'] = 'coloredrows';
        } else {
            $this->attributes['class'] .= ' coloredrows';
        }

        $this->options = [];
        $this->options[1] = get_string('student_approve', 'openbook');
        $this->options[2] = get_string('student_reject', 'openbook');

        if (empty($files) || count($files) == 0) {
            return 0;
        }

        foreach ($files as $file) {
            $this->data[] = $this->add_file($file);
        }

        return count($this->data);
    }

    /**
     * Returns a boolean with file approve status
     *
     * @param \stored_file $file Stored file instance
     * @return string
     */
    public function is_file_approved($file) {
        global $OUTPUT;
        $templatecontext = new \stdClass();

        // Now add the specific data to the table!
        $teacherapproval = $this->openbook->teacher_approval($file);
        $obtainteacherapproval = $this->openbook->get_instance()->obtainteacherapproval;

        $teacherapproved = false;
        $teacherdenied = false;
        $teacherpending = false;

        if ($obtainteacherapproval == 1) {
            if ($teacherapproval == 1) {
                $teacherapproved = true;
            } else if ($teacherapproval == 2) {
                $teacherdenied = true;
            } else {
                $teacherpending = true;
            }
        } else {
            $teacherapproved = true;
        }

        // If it is a common teacher file, set $teacherapproved!
        if ($this->openbook->commonteacherfile($file)) {
            $teacherapproved = true;
        }

        return $teacherapproved;
    }

    /**
     * Returns a string with file approval status
     *
     * @param \stored_file $file Stored file instance
     * @return string
     */
    public function get_approval_status_for_file($file) {
        global $OUTPUT;
        $templatecontext = new \stdClass();
        // Now add the specific data to the table!
        $teacherapproval = $this->openbook->teacher_approval($file);
        $studentapproval = $this->openbook->student_approval($file);
        $commonteacherfile = $this->openbook->commonteacherfile($file);

        $obtainteacherapproval = $this->openbook->get_instance()->obtainteacherapproval;
        $obtainstudentapproval = $this->openbook->get_instance()->obtainstudentapproval;

        $hint = '';

        /* Add teacher approval to hint string. */

        $teacherapproved = false;
        $teacherdenied = false;
        $teacherpending = false;

        if ($obtainteacherapproval == 1) {
            if ($teacherapproval == 1) {
                $teacherapproved = true;
                $hint .= get_string('teacher_approved', 'openbook');
            } else if ($teacherapproval == 2) {
                $teacherdenied = true;
                $hint .= get_string('teacher_rejected', 'openbook');
            } else {
                $teacherpending = true;
                $hint .= get_string('teacher_pending', 'openbook');
            }
        } else {
            $teacherapproved = true;
            $hint .= get_string('teacher_approved_automatically', 'openbook');
        }

        $hint .= ' ';

        /* Add student approval to hint string. */

        $studentapproved = false;
        $studentdenied = false;
        $studentpending = false;

        if ($this->openbook->get_filesarepersonal_status() == "0") {
            if ($obtainstudentapproval == 1) {
                if ($studentapproval == 1) {
                    $studentapproved = true;
                    $hint .= get_string('student_approved', 'openbook');
                } else if ($studentapproval == 2) {
                    $studentdenied = true;
                    $hint .= get_string('student_rejected', 'openbook');
                } else {
                    if ($this->openbook->is_approval_open()) {
                        $this->changepossible = true;
                        return \html_writer::select($this->options, 'studentapproval[' . $file->get_id() . ']', $studentapproval);
                    }
                    $studentpending = true;
                    $hint .= get_string('student_pending', 'openbook');
                }
            } else {
                $studentapproved = true;
                $hint .= get_string('student_approved_automatically', 'openbook');
            }
        }

        /* Use $hint string in context */

        $templatecontext->hint = $hint;

        /* Set approval icons */

        if ($teacherpending) {
            $templatecontext->icon = $this->questionmark;
        } else if (!$teacherapproved) {
            $templatecontext->icon = $this->invalid;
        } else {
            if ($studentapproved && $this->openbook->get_filesarepersonal_status() == "0") {
                $templatecontext->icon = $this->share;
            } else {
                $templatecontext->icon = $this->valid;
            }
        }

        return $OUTPUT->render_from_template('mod_openbook/approval_icon', $templatecontext);
    }

    /**
     * Get all files, in which the current user is involved
     *
     * @return \stored_file[] array of stored_files indexed by pathanmehash
     */
    public function get_files() {
        global $USER;

        if ($this->files !== null) {
            return $this->files;
        }

        $contextid = $this->openbook->get_context()->id;
        $filearea = 'attachment';
        $itemid = $USER->id;

        $files = $this->fs->get_area_files($contextid, 'mod_openbook', $filearea, $itemid, 'timemodified', false);

        foreach ($files as $file) {
            if ($file->get_filepath() == '/resources/') {
                $this->resources[] = $file;
            } else {
                $this->files[] = $file;
            }
            if ($this->lastmodified < $file->get_timemodified()) {
                $this->lastmodified = $file->get_timemodified();
            }
        }

        return $this->files;
    }

    /**
     * Returns if it's possible to change the approval
     *
     * @return bool
     */
    public function changepossible() {
        $result = ($this->changepossible ? true : false) && has_capability(
            'mod/openbook:upload',
            $this->openbook->get_context()
        );
        return $result;
    }

    /**
     * Add a single file to the table
     *
     * @param \stored_file $file Stored file instance
     * @return string[] Array of table cell contents
     */
    public function add_file(\stored_file $file) {
        global $OUTPUT;

        $data = [];
        $data[] = $OUTPUT->pix_icon(file_file_icon($file), get_mimetype_description($file));

        $filename = $file->get_filename();
        $maxlen = 65;

        if (strlen($filename) > $maxlen) {
            $displayname = \core_text::substr($filename, 0, $maxlen - 3) . '...';
        } else {
            $displayname = $filename;
        }

        if ($this->is_file_approved($file)) {
            $pluginurl = \moodle_url::make_pluginfile_url(
                $file->get_contextid(),
                $file->get_component(),
                $file->get_filearea(),
                $file->get_itemid(),
                $file->get_filepath(),
                $file->get_filename(),
                false
            );

            if (
                $this->openbook->get_openpdffilesinpdfjs_status() == "1" &&
                $file->get_mimetype() == "application/pdf"
            ) {
                $pdfviewer = ($this->openbook->get_uselegacyviewer_status() == "1")
                    ? 'pdfjs-legacy-dist'
                    : 'pdfjs-dist';
                $pdfjsurl = new \moodle_url('/mod/openbook/' . $pdfviewer . '/web/viewer.html', [
                    'file' => $pluginurl->out(),
                ]);
                $url = $pdfjsurl;
            } else {
                $dlurl = new \moodle_url('/mod/openbook/view.php', [
                        'id' => $this->openbook->get_coursemodule()->id,
                        'download' => $file->get_id(),
                ]);
                $url = $dlurl;
            }

            $data[] = \html_writer::link(
                $url,
                $displayname,
                ['target' => '_blank', 'rel' => 'noopener noreferrer', 'title' => $filename]
            );
        } else {
            // Disactivated links.
            $data[] = \html_writer::tag('a', $displayname, [
                'class' => 'disabled-link',
                'href' => '#',
                'onclick' => 'return false;',
                'title' => 'Ce fichier est indisponible',
            ]);
        }

        $data[] = $this->get_approval_status_for_file($file);

        // The specific data will be added in the child-classes!

        return $data;
    }
}
