<?php
// This file is part of
//
// 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/>.

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

require_once('../../lib.php');

function create_submission ($data, $gradeimporterid, $userid) {
  global $DB;
  $timenow = time();
  if (empty($data->id)) {
    // If is new db entry;
    $data->gradeimporterid = $gradeimporterid;
    $data->usermodified = $userid;
    $data->timecreated = $timenow;

    $isnewentry = true;
  } else {
    $isnewentry = false;
  }

  $data->introformat = $data->intro["format"];
  $data->intro = $data->intro["text"];
  $data->timemodified = $timenow;
  $data->position = -1; // Do later

  if ($isnewentry) {
    // If is new entry insert data into DB and gets id
    $data->id = $DB->insert_record('gradeimporter_submission', $data);
  }

  // If not new entry updates information
  // If new entry inserts id into DB
  $DB->update_record('gradeimporter_submission', $data);

  return $data;
}



function store_files ($context, $cm, $data) {
  global $CFG;
  $fs = get_file_storage();
  $files = $fs->get_area_files($context->id, 'mod_gradeimporter',
                'submissionfiles', $data->id
              );
  foreach ($files as $file) {
    if ($file->get_mimetype() == 'text/csv') {
      read_csv($file->get_content(), $context, $data);
      return;
    }
    if ($file->get_mimetype() == 'application/zip') {
      // If it is a .zip file, extract files from the zip
      $zipfiles = read_zip($file, $context, $fs);
      // Search a .csv file
      foreach ($zipfiles as $file) {

        if ($file->get_mimetype() == 'text/csv') {
          // If csv is found, pass it to read_csv()
          read_csv($file->get_content(), $context, $data, $zipfiles);
          // Only expects one csv so doesn't look for another
        }
      }
      // Finished processing files from zip, so delete temp copies
      $fs->delete_area_files($context->id, 'mod_gradeimporter', 'unpacktemp', 0);
    }
  }
}

function read_csv ($content, $context, $data, $zipfiles = null) {

  $csv = prepare_csv($content);
  foreach ($csv as $line => $feedback) {
    $feedback = fix_feedback($feedback, $line); // Check if data is correct
    $feedbackid = store_feedback($feedback, $context->id, $data->id);
    gradeimporter_update_grades($data, $feedback['id']);
    if ($feedback['file'] != "") {
      // If feedback has associated file, insert it into pluginfile
      foreach ($zipfiles as $file) {
        // Search in zipfiles to find same name then feedback['file']
        if ($feedback['file'] == $file->get_filename()) {
          $feedbackfileinfo = store_feedback_file($feedback, $context, $data, $file, $feedbackid);
          break;
        }
      }
    }
  }
}

function prepare_csv ($content) {
  $csvlines = explode(PHP_EOL, $content);
  $csv = array();
  foreach ($csvlines as $line) {
    $csv[] = str_getcsv($line);
  }
  $header = array_shift($csv);

  $outputcsv = array();
  $outputcsv = array_map(
              function($v)use($header){
                return array_combine($header, $v);
              },
              $csv
            );

  return $outputcsv;
}

function store_feedback ($feedback, $contextid, $submissionid) {
  global $DB, $USER;
  // Prepare data to submit to gradeimporter_feedback table
  $entry = feedback_exists($feedback, $submissionid);
  $isnewentry = false;
  if (!$entry) {
    $entry = new stdClass();
    $entry->id = null;
    $entry->timecreated = time();
    $entry->submissionid = $submissionid;
    $entry->studentid = $feedback['id'];
    $entry->contextid = $contextid;
    $isnewentry = true;
  } else {
    // If already had a feedback
    // Deletes its files and remove its entry on DB
    delete_feedback_files($entry);
    $DB->delete_records('gradeimporter_feedback',
                          array('submissionid' => $submissionid,
                                'studentid' => $feedback['id'])
                        );
  }

  $entry->timemodified = time();
  $entry->grade = $feedback['grade'];
  $entry->comment = $feedback['comment'];
  $entry->filename = $feedback['file'];
  $entry->usermodified = $USER->id;

  // If is not a new feedback update previous record and return id
  return $DB->insert_record('gradeimporter_feedback', $entry);
}

function store_feedback_file ($feedback, $context, $submission, $filetostore, $feedbackid) {
  // Prepare file
  $fs = get_file_storage();
  // Create file information needed
  $fileinfo = array(
    'contextid' => $context->id,
    'component' => 'mod_gradeimporter',
    'filearea' => 'submissionfiles',
    'itemid' => $feedbackid,
    'filepath' => "/",
    'filename' => $filetostore->get_filename(),
    'timecreated' => time(), 'timemodified' => time()
  );

  // Store files in correct area
  return $fs->create_file_from_storedfile($fileinfo, $filetostore);
}

function read_zip ($file, $context, $fs) {
  global $CFG;
  // Get file packer to unpack zip
  $packer = get_file_packer('application/zip');

  // Clear area_files if it has been used before
  $fs->delete_area_files($context->id,
              'mod_gradeimporter',
              'unpacktemp'
            );

  // Extract to temp areafiles
  $file->extract_to_storage($packer,
                $context->id,
                'mod_gradeimporter',
                'unpacktemp',
                0,
                $CFG->tempdir,
                false
              );

  // Get extracted files from unpacktemp area file
  $tempfiles = $fs->get_area_files($context->id,
                  'mod_gradeimporter',
                  'unpacktemp'
            );

  // Returns an array of files object
  return $tempfiles;
}

function get_types_array($gradeimporterid) {
  global $DB, $CFG;
  // Gets moodle table prefix, usually mdl_
  $tp = $CFG->prefix;
  $query = "select id, name from {$tp}gradeimporter_submissiontype where gradeimporterid = $gradeimporterid";
  return $DB->get_records_sql($query);
}

function validate_formdata($data) {
  if ($data->type == -1) {
    throw new moodle_exception(get_string('invalidtype', 'gradeimporter'));
  }
}

function feedback_exists($feedback, $submissionid) {
  global $DB;
  $feedback = $DB->get_record('gradeimporter_feedback',
                              array('submissionid' => $submissionid,
                                      'studentid' => $feedback['id']),
                              );
  return $feedback;
}

/**
 * Searches if a feedback has a file when updating it
 * If already has file then delete it to open space for a new file
 * Or if updated feedback doesnt have associated file
 * @param $feedback - record of already submited feedback
 * @return void
 */
function delete_feedback_files($feedback) {
  $fs = get_file_storage();
  $file = $fs->get_file($feedback->contextid, 'mod_gradeimporter', 'submissionfiles', $feedback->id, '/', $feedback->filename);
  if ($file) {
    $file->delete();
  }
}

/**
 * Checks if $feedback csv line is correct
 * if id is missing throw error
 * if grade is missing change it to 0
 * @param array $feedback - line with feedback data for a student
 * @param int $line - which line of the csv file the feedback is
 * @return array $feedback - Either empty grade changed to 0 or the same as param
 */
function fix_feedback ($feedback, $line) {
  if ($feedback['id'] == "") {
    throw new moodle_exception(get_string('studentidmissing', 'gradeimporter'), $line);
  }
  if ($feedback['grade'] == "") {
    $feedback['grade'] = 0;
  }
  return $feedback;
}


function delete_feedback($feedback) {
  global $DB;
  delete_feedback_files($feedback);
  $DB->delete_records('gradeimporter_feedback',
                      array('submissionid' => $feedback->submissionid,
                            'studentid' => $feedback->studentid)
                    );
}