<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

require_once("../../config.php");

require_login();

global $DB, $USER, $COURSE;

class Performance {

  private string $emptyPerformance = '{"type":[{"type":"Leitura e Escrita","total":0,"errors":0},{"type":"Manipulação de Entrada","total":0,"errors":0},{"type":"Lógica","total":0,"errors":0},{"type":"Matemática","total":0,"errors":0},{"type":"Condição","total":0,"errors":0},{"type":"Laço","total":0,"errors":0},{"type":"Vetor","total":0,"errors":0}],"tag":[{"tag":"Caso Geral","total":0,"errors":0},{"tag":"Caso Limite","total":0,"errors":0},{"tag":"Caso Nulo","total":0,"errors":0},{"tag":"Caso Negativo","total":0,"errors":0},{"tag":"Igualdade","total":0,"errors":0},{"tag":"Tipo de Entrada","total":0,"errors":0}],"lastTypeErrors":[],"lastTagErrors":[]}';
    
  public function __construct() {
    global $DB;
  }

  private function add(string $course, string $student): void {
    global $DB;
    $DB->insert_record('iassign_performance', (object)array('course' => $course, 'student' => $student, 'performance' => $this->emptyPerformance),false);
  }

  public function find(string $course, string $student): array {
    global $DB;
    $selectPerformance = $DB->get_record('iassign_performance', array('course' => $course, 'student' => $student));
    if (!$selectPerformance) {
      $this->add($course,$student);
      $performance = (array)$DB->get_record('iassign_performance', array('course' => $course, 'student' => $student));
    }
    else {
        $performance = (array)$selectPerformance;
    }
    return $performance;
  }

  public function update(string $course, string $student, array $testCases, array $exerciseType, object $jsPerformance): void {
    global $DB;
    $performance = json_decode($this->find($course,$student)['performance']);
    $incorrect = $this->updateTags($testCases, $performance->tag, $performance);
    $this->updateTypes($exerciseType, $performance->type, $performance, $incorrect);

    if ($performance!=$jsPerformance) {
      echo "Houve uma tentativa irregular de alterar o banco de dados";
    }

    $newPerformance = json_encode($performance, JSON_UNESCAPED_UNICODE);

    $DB->update_record('iassign_performance', (object)array('id' => $this->find($course,$student)['id'], 'course' => $course, 'student' => $student, 'performance' => $newPerformance),false);
  }

  private function updateTypes(array $exerciseType, array $types, object $performance, bool $incorrect): void {
    for($i=0; $i<count($exerciseType); $i++){
      for($j=0; $j<count($types); $j++){
        if ($exerciseType[$i] == $types[$j]->type) {
          $types[$j]->total += 1;
          if ($incorrect) {
            $types[$j]->errors += 1;
            array_push($performance->lastTypeErrors,$exerciseType[$i]);
            if (count($performance->lastTypeErrors) > 50) {
              array_shift($performance->lastTypeErrors);
            }
          }
        }
      }
    }
  }

  private function updateTags(array $testCases, array $tags, object $performance): bool {
    $incorrect = false;
    for ($i=0; $i<count($testCases); $i++) {
      for ($j=0; $j<count($tags); $j++) {
        if (implode("",$testCases[$i]->tags) === $tags[$j]->tag) {
          $tags[$j]->total += 1;
          if (!$testCases[$i]->results[0]->grade) {
            $incorrect = true;
            $tags[$j]->errors += 1;
            array_push($performance->lastTagErrors,implode("",$testCases[$i]->tags));
            if (count($performance->lastTagErrors) > 50) {
              array_shift($performance->lastTagErrors);
            }
          }
        }
      }
    }
    return $incorrect;
  }

}

if ($_SERVER['REQUEST_METHOD'] === 'GET') {
  $performance = new Performance();
  $student_performance = $performance->find(get_coursemodule_from_id('iassign',explode("D",explode("%2",explode("id",explode("get_answer",$_SERVER['HTTP_REFERER'])[1])[1])[0])[1])->id, $USER->id)['performance'];
  echo $student_performance;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $performance = new Performance();
  $data = $_POST["data"];
  $obj = json_decode($data);
  $performance->update(get_coursemodule_from_id('iassign',explode("D",explode("%2",explode("id",explode("get_answer",$_SERVER['HTTP_REFERER'])[1])[1])[0])[1])->id, $USER->id, $obj->testCases, $obj->exerciseType, $obj->performance);
}