<?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/>.

/**
 * Description of Annotation
 * Methods:
 * create_annotation
 * delete
 * read (abstract)
 *
 * @package   mod_pdfannotator
 * @copyright 2018 RWTH Aachen (see README.md)
 * @author    Rabea de Groot, Anna Heynkes and Friederike Schwager
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 *
 */
defined('MOODLE_INTERNAL') || die();

class pdfannotator_annotation {

    /**
     * This method creates a new record in the database table named mdl_pdfannotator_annotations and returns its id
     *
     * @param type $documentid specifies the pdf file to which this annotation belongs
     * @param type $pageid specifies the page within that pdf file
     * @param type $type child class (highlight, strikeout, area, textbox, drawing, comment or point)
     * @param type $itemid identifies the record in the respective child class table, e.g. highlights
     * @return int (or boolean false)
     */
    public static function create_annotation($documentid, $pageid, $type, $itemid) {

        global $DB;
        global $USER;
        $datarecord = new stdClass();
        $datarecord->userid = $USER->id;
        $datarecord->documentid = $documentid;
        $datarecord->pageid = $pageid;
        $datarecord->type = $type;
        $datarecord->itemid = $itemid;
        $annotationid = $DB->insert_record('pdfannotator_annotations', $datarecord, $returnid = true);
        return $annotationid;
    }

    /**
     * Method updates data attribute (consisting of width, color and lines)
     * in mdl_pdfannotator_drawings after a drawing was shifted in position
     *
     * @param type $annotationid
     * @param type $newdata
     * @return type int 1 for success
     */
    public static function update($annotationid, $newdata) {
        global $DB, $USER;

        $annotation = $DB->get_record('pdfannotator_annotations', ['id' => $annotationid]);
        if ($annotation) {
            $annotation->data = json_encode($newdata);
            $annotation->timemodified = time();
            $annotation->modifiedby = $USER->id;
            $time = pdfannotator_get_user_datetime($annotation->timemodified);
            $success = $DB->update_record('pdfannotator_annotations', $annotation);
        } else {
            $success = false;
        }

        if ($success) {
            $result = array('status' => 'success', 'timemoved' => $time);
            if ($annotation->userid != $USER->id) {
                $result['movedby'] = pdfannotator_get_username($USER->id);
            }
            return $result;
        } else {
            return ['status' => 'error'];
        }
    }

    /**
     * Method deletes the specified annotation and all comments attached to it,
     * if the user is allowed to do so.
     * Teachers are allowed to delete any comment, students may only delete their own comments.
     *
     * @param type $annotationId
     * @param type $cmid
     * @param type $deleteanyway Delete annotation in any case. F.e. if right to be forgotten was invoked or
     *  a user without the capability to delete the annotation deletes it implicitly by deleting the last comment of the annotation
     * @return boolean
     */
    public static function delete($annotationid, $cmid = null, $deleteanyway = null) {

        global $DB;
        $annotation = $DB->get_record('pdfannotator_annotations', array('id' => $annotationid), '*', $strictness = IGNORE_MISSING);
        if (!$annotation) {
            return false;
        }

        // Check user rights to delete this annotation and all its attached comments.
        $deletionallowed = self::deletion_allowed($annotation, $cmid);

        // Delete annotation.
        if ($deletionallowed[0] === true || $deleteanyway === true) {

            // Delete all comments of this annotation.
            $comments = $DB->get_records('pdfannotator_comments', array("annotationid" => $annotationid));
            foreach ($comments as $commentdata) {
                $DB->delete_records('pdfannotator_votes', array("commentid" => $commentdata->id));
            }
            $success = $DB->delete_records('pdfannotator_comments', array("annotationid" => $annotationid));

            // Delete subscriptions to the question.
            $DB->delete_records('pdfannotator_subscriptions', array('annotationid' => $annotationid));

            // Delete the annotation itself.
            $success = $DB->delete_records('pdfannotator_annotations', array("id" => $annotationid));

            if ($deleteanyway) {
                return;
            }

            if (!$success) {
                return false;
            }

            return true;
        } else {
            return $deletionallowed[1];
        }
    }

    /**
     * Method checks whether the annotation as well as possible comments attached to it
     * belong to the current user.     *
     * @return
     */
    public static function deletion_allowed($annotation, $cmid) {

        global $DB, $USER;
        $userid = $USER->id;
        $author = $annotation->userid;

        $result = [];

        // If user has admin rights with regard to annotations/comments: Allow deletion.
        $cm = get_coursemodule_from_id('pdfannotator', $cmid, 0, false, MUST_EXIST);
        $context = context_module::instance($cm->id);
        $deleteany = has_capability('mod/pdfannotator:deleteany', $context);
        $deleteown = has_capability('mod/pdfannotator:deleteown', $context);
        if ($deleteany) {
            $result[] = true;
        } else if (($author !== $userid) || !$deleteown) {
            $result[] = false;
            $result[] = get_string('onlyDeleteOwnAnnotations', 'pdfannotator');
        } else if ($DB->record_exists_select('pdfannotator_comments', "annotationid = ? AND userid != ?",
            [$annotation->id, $userid])) { // Check whether other people have commented this annotation.
            $result[] = false;
            $result[] = get_string('onlyDeleteUncommentedPosts', 'pdfannotator');
        } else {
            $result[] = true;
        }

        return $result;
    }

    /**
     * Method checks whether the annotation in question may be shifted in position.
     * It returns true if the annotation was made by the user who is trying to shift it and no other person has answered
     * or if that user is an admin.
     *
     * @param type $annotationId
     * @return boolean
     */
    public static function shifting_allowed($annotationid, $context) {
        global $DB;
        global $USER;
        $editanypost = has_capability('mod/pdfannotator:editanypost', $context);
        $editownpost = has_capability('mod/pdfannotator:edit', $context);
        if ($editanypost) {
            return true;
        }
        if (!$editownpost || $USER->id != self::get_author($annotationid)) {
            return false;
        } else if ($DB->record_exists_select('pdfannotator_comments', "annotationid = ? AND userid != ?",
            array($annotationid, $USER->id))) {
            // Annotation was answered by other users.
            return false;
        }
        return true;
    }

    /**
     * Return information for the dummy-comment of a textbox or drawing
     * @param type $annotationid
     */
    public static function get_information($annotationid) {
        global $DB;
        $annotation = $DB->get_record('pdfannotator_annotations', ['id' => $annotationid]);
        $annotationtype = $DB->get_field('pdfannotator_annotationtypes', 'name', ['id' => $annotation->annotationtypeid]);

        if ($annotationtype === "textbox" || $annotationtype === "drawing") {
            $comment = new stdClass();
            $comment->type = $annotationtype;
            $comment->content = '';
            $comment->displaycontent = get_string('noCommentsupported', 'pdfannotator');
            $comment->userid = $annotation->userid;
            $comment->username = pdfannotator_get_username($annotation->userid);
            $comment->visibility = 'public';
            $comment->timecreated = pdfannotator_get_user_datetime($annotation->timecreated);
            if (!empty($annotation->timemodified) && $annotation->timemodified != $comment->timecreated) {
                $comment->repositioned = true;
                $comment->timemoved = pdfannotator_get_user_datetime($annotation->timemodified);
                if (!empty($annotation->modifiedby) && $annotation->modifiedby != $annotation->userid) {
                    $comment->movedby = $annotation->modifiedby;
                } else {
                    $comment->movedby = null;
                }
            }
            $comment->usevotes = 0;
            $comment->uuid = -1; // TODO.
            $comment->annotation = $annotationid;
            $comment->isdeleted = 0;
            $comment->isquestion = 1;
            $comment->solved = 0;

            return $comment;
        } else {
            return false;
        }
    }

    /**
     * Method takes an annotation's id and returns the user id of its author
     *
     * @param type $itemid
     * @return type
     */
    public static function get_author($annotationid) {

        global $DB;
        return $DB->get_field('pdfannotator_annotations', 'userid', array('id' => $annotationid), $strictness = MUST_EXIST);
    }

    /**
     * Method takes an annotation's id and returns the page it was made on
     *
     * @param type $annotationId
     * @return type
     */
    public static function get_pageid($annotationid) {
        global $DB;
        return $DB->get_field('pdfannotator_annotations', 'page', array('id' => $annotationid), $strictness = IGNORE_MISSING);
    }

    /**
     * Method takes an annotation's id and returns the content of the underlying question comment
     *
     * @param type $annotationId
     * @return type
     */
    public static function get_question($annotationid) {
        global $DB;
        $question = $DB->get_record('pdfannotator_comments', ['annotationid' => $annotationid, 'isquestion' => 1], 'content');
        return $question->content;
    }

}
