<?php
/* For licensing terms, see /license.txt */

use ChamiloSession as Session;

/**
 * Upload quiz: This script shows the upload quiz feature.
 */
$help_content = 'exercise_upload';
require_once __DIR__.'/../inc/global.inc.php';

api_protect_course_script(true);

$is_allowed_to_edit = api_is_allowed_to_edit(null, true);
$debug = false;
$origin = api_get_origin();
if (!$is_allowed_to_edit) {
    api_not_allowed(true);
}

$this_section = SECTION_COURSES;
$htmlHeadXtra[] = "<script>
$(function(){
    $('#user_custom_score').click(function() {
        $('#options').toggle();
    });
});
</script>";

// Action handling
lp_upload_quiz_action_handling();

$interbreadcrumb[] = [
    'url' => 'exercise.php?'.api_get_cidreq(),
    'name' => get_lang('Tests'),
];

Display::display_header(get_lang('Import quiz from Excel'), 'Exercises');

echo '<div class="actions">';
echo lp_upload_quiz_actions();
echo '</div>';

// the main content
lp_upload_quiz_main();

function lp_upload_quiz_actions()
{
    $return = '<a href="exercise.php?'.api_get_cidreq().'">'.
        Display::return_icon(
            'back.png',
            get_lang('BackToTestsList'),
            '',
            ICON_SIZE_MEDIUM
        ).'</a>';

    return $return;
}

function lp_upload_quiz_main()
{
    $lp_id = isset($_GET['lp_id']) ? (int) $_GET['lp_id'] : null;

    $form = new FormValidator(
        'upload',
        'POST',
        api_get_self().'?'.api_get_cidreq().'&lp_id='.$lp_id,
        '',
        ['enctype' => 'multipart/form-data']
    );
    $form->addElement('header', get_lang('Import quiz from Excel'));
    $form->addElement('file', 'user_upload_quiz', get_lang('File upload'));

    $link = '<a href="../exercise/quiz_template.xls">'.
        Display::return_icon('export_excel.png', get_lang('Download the Excel Template')).get_lang('Download the Excel Template').'</a>';
    $form->addElement('label', '', $link);

    $table = new HTML_Table(['class' => 'table']);

    $tableList = [
        UNIQUE_ANSWER => get_lang('Multiple choice'),
        MULTIPLE_ANSWER => get_lang('Multiple answers'),
        FILL_IN_BLANKS => get_lang('Fill blanks or form'),
        MATCHING => get_lang('Matching'),
        FREE_ANSWER => get_lang('Open question'),
        GLOBAL_MULTIPLE_ANSWER => get_lang('Global multiple answer'),
    ];

    $table->setHeaderContents(0, 0, get_lang('Question type'));
    $table->setHeaderContents(0, 1, '#');

    $row = 1;
    foreach ($tableList as $key => $label) {
        $table->setCellContents($row, 0, $label);
        $table->setCellContents($row, 1, $key);
        $row++;
    }
    $table = $table->toHtml();

    $form->addElement('label', get_lang('Question type'), $table);
    $form->addElement(
        'checkbox',
        'user_custom_score',
        null,
        get_lang('Use custom score for all questions'),
        ['id' => 'user_custom_score']
    );
    $form->addElement('html', '<div id="options" style="display:none">');
    $form->addElement('text', 'correct_score', get_lang('Correct score'));
    $form->addElement('text', 'incorrect_score', get_lang('Incorrect score'));
    $form->addElement('html', '</div>');

    $form->addRule('user_upload_quiz', get_lang('Required field'), 'required');

    $form->addProgress();
    $form->addButtonUpload(get_lang('Upload'), 'submit_upload_quiz');
    $form->display();
}

/**
 * Handles a given Excel spreadsheets as in the template provided.
 */
function lp_upload_quiz_action_handling()
{
    if (!isset($_POST['submit_upload_quiz'])) {
        return;
    }

    $_course = api_get_course_info();

    if (empty($_course)) {
        return false;
    }

    $courseId = $_course['real_id'];

    // Get the extension of the document.
    $path_info = pathinfo($_FILES['user_upload_quiz']['name']);

    // Check if the document is an Excel document
    if (!in_array($path_info['extension'], ['xls', 'xlsx'])) {
        return;
    }

    // Variables
    $numberQuestions = 0;
    $question = [];
    $scoreList = [];
    $feedbackTrueList = [];
    $feedbackFalseList = [];
    $questionDescriptionList = [];
    $noNegativeScoreList = [];
    $questionTypeList = [];
    $answerList = [];
    $quizTitle = '';

    $objPHPExcel = PHPExcel_IOFactory::load($_FILES['user_upload_quiz']['tmp_name']);
    $objPHPExcel->setActiveSheetIndex(0);
    $worksheet = $objPHPExcel->getActiveSheet();
    $highestRow = $worksheet->getHighestRow(); // e.g. 10
    $highestColumn = $worksheet->getHighestColumn(); // e.g 'F'

    $correctScore = isset($_POST['correct_score']) ? $_POST['correct_score'] : null;
    $incorrectScore = isset($_POST['incorrect_score']) ? $_POST['incorrect_score'] : null;
    $useCustomScore = isset($_POST['user_custom_score']) ? true : false;

    for ($row = 1; $row <= $highestRow; $row++) {
        $cellTitleInfo = $worksheet->getCellByColumnAndRow(0, $row);
        $cellDataInfo = $worksheet->getCellByColumnAndRow(1, $row);
        $cellScoreInfo = $worksheet->getCellByColumnAndRow(2, $row);
        $title = $cellTitleInfo->getValue();

        switch ($title) {
            case 'Quiz':
                $quizTitle = $cellDataInfo->getValue();
                break;
            case 'Question':
                $question[] = $cellDataInfo->getValue();
                // Search cell with Answer title
                $answerRow = $row;
                $continue = true;
                $answerIndex = 0;
                while ($continue) {
                    $answerRow++;
                    $answerInfoTitle = $worksheet->getCellByColumnAndRow(0, $answerRow);
                    $answerInfoData = $worksheet->getCellByColumnAndRow(1, $answerRow);
                    $answerInfoExtra = $worksheet->getCellByColumnAndRow(2, $answerRow);
                    $answerInfoTitle = $answerInfoTitle->getValue();
                    if (strpos($answerInfoTitle, 'Answer') !== false) {
                        $answerList[$numberQuestions][$answerIndex]['data'] = $answerInfoData->getValue();
                        $answerList[$numberQuestions][$answerIndex]['extra'] = $answerInfoExtra->getValue();
                    } else {
                        $continue = false;
                    }
                    $answerIndex++;

                    // To avoid loops
                    if ($answerIndex > 60) {
                        $continue = false;
                    }
                }

                // Search cell with question type
                $answerRow = $row;
                $continue = true;
                $questionTypeIndex = 0;
                while ($continue) {
                    $answerRow++;
                    $questionTypeTitle = $worksheet->getCellByColumnAndRow(0, $answerRow);
                    $questionTypeExtra = $worksheet->getCellByColumnAndRow(2, $answerRow);
                    $title = $questionTypeTitle->getValue();
                    if ($title == 'QuestionType') {
                        $questionTypeList[$numberQuestions] = $questionTypeExtra->getValue();
                        $continue = false;
                    }
                    if ($title == 'Question') {
                        $continue = false;
                    }
                    // To avoid loops
                    if ($questionTypeIndex > 60) {
                        $continue = false;
                    }
                    $questionTypeIndex++;
                }

                // Detect answers
                $numberQuestions++;
                break;
            case 'Score':
                $scoreList[] = $cellScoreInfo->getValue();
                break;
            case 'NoNegativeScore':
                $noNegativeScoreList[] = $cellScoreInfo->getValue();
                break;
            case 'Category':
                $categoryList[] = $cellDataInfo->getValue();
                break;
            case 'FeedbackTrue':
                $feedbackTrueList[] = $cellDataInfo->getValue();
                break;
            case 'FeedbackFalse':
                $feedbackFalseList[] = $cellDataInfo->getValue();
                break;
            case 'EnrichQuestion':
                $questionDescriptionList[] = $cellDataInfo->getValue();
                break;
        }
    }

    $propagateNegative = 0;
    if ($useCustomScore && !empty($incorrectScore)) {
        if ($incorrectScore < 0) {
            $propagateNegative = 1;
        }
    }

    if ($quizTitle != '') {
        // Variables
        $type = 2;
        $random = $active = $results = $max_attempt = $expired_time = 0;
        // Make sure feedback is enabled (3 to disable), otherwise the fields
        // added to the XLS are not shown, which is confusing
        $feedback = 0;

        // Quiz object
        $exercise = new Exercise();
        $exercise->updateTitle($quizTitle);
        $exercise->updateExpiredTime($expired_time);
        $exercise->updateType($type);
        $exercise->setRandom($random);
        $exercise->active = $active;
        $exercise->updateResultsDisabled($results);
        $exercise->updateAttempts($max_attempt);
        $exercise->updateFeedbackType($feedback);
        $exercise->updatePropagateNegative($propagateNegative);
        $quiz_id = $exercise->save();

        if ($quiz_id) {
            // Import questions.
            for ($i = 0; $i < $numberQuestions; $i++) {
                // Question name
                $questionTitle = $question[$i];
                $myAnswerList = isset($answerList[$i]) ? $answerList[$i] : [];
                $description = isset($questionDescriptionList[$i]) ? $questionDescriptionList[$i] : '';
                $categoryId = null;
                if (isset($categoryList[$i]) && !empty($categoryList[$i])) {
                    $categoryName = $categoryList[$i];
                    $categoryId = TestCategory::get_category_id_for_title($categoryName, $courseId);
                    if (empty($categoryId)) {
                        $category = new TestCategory();
                        $category->name = $categoryName;
                        $categoryId = $category->save();
                    }
                }

                $question_description_text = '<p></p>';
                if (!empty($description)) {
                    // Question description.
                    $question_description_text = "<p>$description</p>";
                }

                // Unique answers are the only question types available for now
                // through xls-format import
                $question_id = null;
                if (isset($questionTypeList[$i]) && $questionTypeList[$i] != '') {
                    $detectQuestionType = (int) $questionTypeList[$i];
                } else {
                    $detectQuestionType = detectQuestionType($myAnswerList);
                }

                /** @var Question $answer */
                switch ($detectQuestionType) {
                    case FREE_ANSWER:
                        $answer = new FreeAnswer();
                        break;
                    case GLOBAL_MULTIPLE_ANSWER:
                        $answer = new GlobalMultipleAnswer();
                        break;
                    case MULTIPLE_ANSWER:
                        $answer = new MultipleAnswer();
                        break;
                    case FILL_IN_BLANKS:
                        $answer = new FillBlanks();
                        $question_description_text = '';
                        break;
                    case MATCHING:
                        $answer = new Matching();
                        break;
                    case UNIQUE_ANSWER:
                    default:
                        $answer = new UniqueAnswer();
                        break;
                }

                if ($questionTitle != '') {
                    $question_id = $answer->create_question(
                        $quiz_id,
                        $questionTitle,
                        $question_description_text,
                        0, // max score
                        $answer->type
                    );

                    if (!empty($categoryId)) {
                        TestCategory::addCategoryToQuestion(
                            $categoryId,
                            $question_id,
                            $courseId
                        );
                    }
                }
                switch ($detectQuestionType) {
                    case GLOBAL_MULTIPLE_ANSWER:
                    case MULTIPLE_ANSWER:
                    case UNIQUE_ANSWER:
                        $total = 0;
                        if (is_array($myAnswerList) && !empty($myAnswerList) && !empty($question_id)) {
                            $id = 1;
                            $objAnswer = new Answer($question_id, $courseId);
                            $globalScore = isset($scoreList[$i]) ? $scoreList[$i] : null;

                            // Calculate the number of correct answers to divide the
                            // score between them when importing from CSV
                            $numberRightAnswers = 0;
                            foreach ($myAnswerList as $answer_data) {
                                if (strtolower($answer_data['extra']) == 'x') {
                                    $numberRightAnswers++;
                                }
                            }

                            foreach ($myAnswerList as $answer_data) {
                                $answerValue = $answer_data['data'];
                                $correct = 0;
                                $score = 0;
                                if (strtolower($answer_data['extra']) == 'x') {
                                    $correct = 1;
                                    $score = isset($scoreList[$i]) ? $scoreList[$i] : 0;
                                    $comment = isset($feedbackTrueList[$i]) ? $feedbackTrueList[$i] : '';
                                } else {
                                    $comment = isset($feedbackFalseList[$i]) ? $feedbackFalseList[$i] : '';
                                    $floatVal = (float) $answer_data['extra'];
                                    if (is_numeric($floatVal)) {
                                        $score = $answer_data['extra'];
                                    }
                                }

                                if ($useCustomScore) {
                                    if ($correct) {
                                        $score = $correctScore;
                                    } else {
                                        $score = $incorrectScore;
                                    }
                                }

                                // Fixing scores:
                                switch ($detectQuestionType) {
                                    case GLOBAL_MULTIPLE_ANSWER:
                                        if ($correct) {
                                            $score = abs($scoreList[$i]);
                                        } else {
                                            if (isset($noNegativeScoreList[$i]) && $noNegativeScoreList[$i] == 'x') {
                                                $score = 0;
                                            } else {
                                                $score = -abs($scoreList[$i]);
                                            }
                                        }
                                        $score /= $numberRightAnswers;
                                        break;
                                    case UNIQUE_ANSWER:
                                        break;
                                    case MULTIPLE_ANSWER:
                                        if (!$correct) {
                                            //$total = $total - $score;
                                        }
                                        break;
                                }

                                $objAnswer->createAnswer(
                                    $answerValue,
                                    $correct,
                                    $comment,
                                    $score,
                                    $id
                                );

                                $total += (float) $score;
                                $id++;
                            }

                            $objAnswer->save();

                            $questionObj = Question::read(
                                $question_id,
                                $_course
                            );

                            if ($questionObj) {
                                switch ($detectQuestionType) {
                                    case GLOBAL_MULTIPLE_ANSWER:
                                        $questionObj->updateWeighting($globalScore);
                                        break;
                                    case UNIQUE_ANSWER:
                                    case MULTIPLE_ANSWER:
                                    default:
                                        $questionObj->updateWeighting($total);
                                        break;
                                }
                                $questionObj->save($exercise);
                            }
                        }
                        break;
                    case FREE_ANSWER:
                        $globalScore = isset($scoreList[$i]) ? $scoreList[$i] : null;
                        $questionObj = Question::read($question_id, $_course);
                        if ($questionObj) {
                            $questionObj->updateWeighting($globalScore);
                            $questionObj->save($exercise);
                        }
                        break;
                    case FILL_IN_BLANKS:
                        $fillInScoreList = [];
                        $size = [];
                        $globalScore = 0;
                        foreach ($myAnswerList as $data) {
                            $score = isset($data['extra']) ? $data['extra'] : 0;
                            $globalScore += $score;
                            $fillInScoreList[] = $score;
                            $size[] = 200;
                        }

                        $scoreToString = implode(',', $fillInScoreList);
                        $sizeToString = implode(',', $size);

                        //<p>Texte long avec les [mots] à [remplir] mis entre [crochets]</p>::10,10,10:200.36363999999998,200,200:0@'
                        $answerValue = $description.'::'.$scoreToString.':'.$sizeToString.':0@';
                        $objAnswer = new Answer($question_id, $courseId);
                        $objAnswer->createAnswer(
                            $answerValue,
                            '', //$correct,
                            '', //$comment,
                            $globalScore,
                            1
                        );

                        $objAnswer->save();

                        $questionObj = Question::read($question_id, $_course);
                        if ($questionObj) {
                            $questionObj->updateWeighting($globalScore);
                            $questionObj->save($exercise);
                        }
                        break;
                    case MATCHING:
                        $globalScore = isset($scoreList[$i]) ? $scoreList[$i] : null;
                        $position = 1;

                        $objAnswer = new Answer($question_id, $courseId);
                        foreach ($myAnswerList as $data) {
                            $option = isset($data['extra']) ? $data['extra'] : '';
                            $objAnswer->createAnswer($option, 0, '', 0, $position);
                            $position++;
                        }

                        $counter = 1;
                        foreach ($myAnswerList as $data) {
                            $value = isset($data['data']) ? $data['data'] : '';
                            $position++;
                            $objAnswer->createAnswer(
                                $value,
                                $counter,
                                ' ',
                                $globalScore,
                                $position
                            );
                            $counter++;
                        }
                        $objAnswer->save();
                        $questionObj = Question::read($question_id, $_course);
                        if ($questionObj) {
                            $questionObj->updateWeighting($globalScore);
                            $questionObj->save($exercise);
                        }
                        break;
                }
            }
        }

        $lpObject = Session::read('lpobject');

        if (!empty($lpObject)) {
            /** @var learnpath $oLP */
            $oLP = UnserializeApi::unserialize('lp', $lpObject);
            if (is_object($oLP)) {
                if ((empty($oLP->cc)) || $oLP->cc != api_get_course_id()) {
                    $oLP = null;
                    Session::erase('oLP');
                    Session::erase('lpobject');
                } else {
                    Session::write('oLP', $oLP);
                }
            }
        }

        if (isset($_SESSION['oLP']) && isset($_GET['lp_id'])) {
            $previous = $_SESSION['oLP']->select_previous_item_id();
            $parent = 0;
            // Add a Quiz as Lp Item
            $_SESSION['oLP']->add_item(
                $parent,
                $previous,
                TOOL_QUIZ,
                $quiz_id,
                $quizTitle,
                ''
            );
            // Redirect to home page for add more content
            header('Location: ../lp/lp_controller.php?'.api_get_cidreq().'&action=add_item&type=step&lp_id='.intval($_GET['lp_id']));
            exit;
        } else {
            //  header('location: exercise.php?' . api_get_cidreq());
            echo '<script>window.location.href = "'.api_get_path(WEB_CODE_PATH).'exercise/admin.php?'.api_get_cidreq().'&exerciseId='.$quiz_id.'&session_id='.api_get_session_id().'"</script>';
        }
    }
}

/**
 * @param array $answers_data
 *
 * @return int
 */
function detectQuestionType($answers_data)
{
    $correct = 0;
    $isNumeric = false;

    if (empty($answers_data)) {
        return FREE_ANSWER;
    }

    foreach ($answers_data as $answer_data) {
        if (strtolower($answer_data['extra']) == 'x') {
            $correct++;
        } else {
            if (is_numeric($answer_data['extra'])) {
                $isNumeric = true;
            }
        }
    }

    if ($correct == 1) {
        $type = UNIQUE_ANSWER;
    } else {
        if ($correct > 1) {
            $type = MULTIPLE_ANSWER;
        } else {
            $type = FREE_ANSWER;
        }
    }

    if ($type == MULTIPLE_ANSWER) {
        if ($isNumeric) {
            $type = MULTIPLE_ANSWER;
        } else {
            $type = GLOBAL_MULTIPLE_ANSWER;
        }
    }

    return $type;
}

if ($origin != 'learnpath') {
    //so we are not in learnpath tool
    Display::display_footer();
}
