<?php
/**
 * @copyright (c) Kufer Software GmbH, Loisachstrasse 4, D-84453 Mühldorf
 */

abstract class CheckFiles
{
  public const UPLOAD_ERROR_DATEI_NICHT_HOCHGELADEN = 'fehler_beim_dateiupload';
  public const UPLOAD_ERROR_DATEINAME_BEGINNT_MIT_PUNKT = 'dateiname_beginnt_mit_punkt';
  public const UPLOAD_ERROR_DATEINAME_MIT_UNERLAUBTEN_ZEICHEN = 'dateiname_mit_unerlaubten_zeichen';
  public const UPLOAD_ERROR_DATEINAME_OHNE_ENDUNG = 'dateiname_ohne_endung';
  public const UPLOAD_ERROR_DATEINAME_MIT_UNERLAUBTER_ENDUNG = 'dateiname_mit_unerlaubter_endung';
  public const UPLOAD_ERROR_MIMETYPE_PASST_NICHT_ZU_ENDUNG = 'mimetype_passt_nicht_zu_endung';
  public const UPLOAD_ERROR_DATEI_ZU_GROSS = 'datei_zu_gross';
  public const UPLOAD_ERROR_DATEI_DUPLIKAT = 'datei_duplikat';
  public const UPLOAD_ERROR_ZU_VIELE_DATEIEN = 'datei_zu_viele_dateien';
  public const UPLOAD_OK = 'datei_ok';

  
  abstract protected function getMaxFileSize();

  public function checkSingleFile(array $pFile, bool $checkDateiendung = true): string
  {
    $checkMimeType = ToolSettingsAPI::getToolSettings(0)->fileUploadCheckMimeType == '1';
    if (UPLOAD_ERR_OK !== $pFile['error']) {
      return self::UPLOAD_ERROR_DATEI_NICHT_HOCHGELADEN;
    } elseif (StringOperations::isDotAtBeginOfString($pFile['name'])) {
      return self::UPLOAD_ERROR_DATEINAME_BEGINNT_MIT_PUNKT;
    } elseif (!CleanOperations::isFileNameWithAllowedChars($pFile['name'])) {
      return self::UPLOAD_ERROR_DATEINAME_MIT_UNERLAUBTEN_ZEICHEN;
    } elseif (strpos($pFile['name'], '.') === false) {
      return self::UPLOAD_ERROR_DATEINAME_OHNE_ENDUNG;
    } elseif ($checkDateiendung
      && StringOperations::isExcludedFileExt(UploadOperations::getBlackOrWhiteListAry(), $pFile['name']) !== '') {
      return self::UPLOAD_ERROR_DATEINAME_MIT_UNERLAUBTER_ENDUNG;
    } elseif ($checkMimeType && $checkDateiendung && !$this->checkMimetype($pFile)) {
      return self::UPLOAD_ERROR_MIMETYPE_PASST_NICHT_ZU_ENDUNG;
    } elseif ($pFile['size'] > $this->getMaxFileSize()) {
      return self::UPLOAD_ERROR_DATEI_ZU_GROSS;
    } else {
      return self::UPLOAD_OK;
    }
  }

  
  public function checkMultipleFiles(array $files, bool $checkDateiendung = true): array
  {
    $maxFileNumber = ToolSettingsAPI::getToolSettings(0)->fileUploadMaxFileNumber;
    $result = array();
    foreach ($files as $field => $file) {
      $filename = $file['name'];
      if ($file['size'] == 0) {
        continue;
      }
      if (count($result) >= $maxFileNumber) {
        $status = self::UPLOAD_ERROR_ZU_VIELE_DATEIEN;
        $result[$filename] = new FileCheckResult($filename, $field, $status, $this->getErrorMessage($status, $file));

        return $result;
      }

      $status = isset($result[$filename]) ? self::UPLOAD_ERROR_DATEI_DUPLIKAT : $this->checkSingleFile($file, $checkDateiendung);
      $result[$filename] = new FileCheckResult($filename, $field, $status, $this->getErrorMessage($status, $file));
    }

    return $result;
  }

  public function getErrorMessage(string $statusCode, array $file): string
  {
    switch ($statusCode) {
      case self::UPLOAD_OK:
        return 'Das Dokument wurde erfolgreich hochgeladen.';
      case self::UPLOAD_ERROR_DATEI_NICHT_HOCHGELADEN:
        return 'Beim Hochladen des Dokuments gab es einen Fehler. Bitte versuchen Sie es erneut.';
      case self::UPLOAD_ERROR_DATEINAME_BEGINNT_MIT_PUNKT:
        return 'Dateinamen dürfen nicht mit einem Punkt beginnen.';
      
      case self::UPLOAD_ERROR_DATEINAME_MIT_UNERLAUBTEN_ZEICHEN:
        return 'Der Dateiname enthält ein nicht erlaubtes Zeichen. Bitte entfernen Sie z.B. Umlaute und Leerzeichen aus dem Dateinamen, und versuchen es erneut.';
      case self::UPLOAD_ERROR_DATEINAME_OHNE_ENDUNG:
        return 'Es dürfen keine Dokumente ohne Dateiendung hochgeladen werden';
      case self::UPLOAD_ERROR_DATEINAME_MIT_UNERLAUBTER_ENDUNG:
        return 'Das Dokument hat eine nicht erlaubte Dateiendung.';
      case self::UPLOAD_ERROR_MIMETYPE_PASST_NICHT_ZU_ENDUNG:
        return 'Der Typ der Datei ' . $file['type'] . ' passt nicht zur Dateiendung ' . StringOperations::getFileExtension($file['name']);
      case self::UPLOAD_ERROR_DATEI_ZU_GROSS:
        return 'Die Datei ist zu groß. Erlaubte Dateigröße: ' . \MathOperations::getBytesUmrechnung($this->getMaxFileSize());
      case self::UPLOAD_ERROR_DATEI_DUPLIKAT:
        return 'Diese Datei ist mehrfach vorhanden. Dateien müssen eindeutigen Namen haben.';
      case self::UPLOAD_ERROR_ZU_VIELE_DATEIEN:
        $zentralsettings = ToolSettingsAPI::getToolSettings(0);

        return 'Es dürfen maximal ' . $zentralsettings->fileUploadMaxFileNumber . ' Dateien hochgeladen werden.';
      default: return '';
    }
  }

  private function checkMimetype(array $file)
  {
    $ext = StringOperations::getFileExtension($file['name']);
    $mimetype = FSOperations::getContentTypeByFileExtension(ltrim($ext, '.'));

    return $mimetype == $file['type'];
  }
}

class FileCheckResult
{
  public $filename;
  public $originField;
  public $status;
  public $statusMessage;

  public function __construct($filename, $originField, $status, $statusMessage)
  {
    $this->filename = $filename;
    $this->originField = $originField;
    $this->status = $status;
    $this->statusMessage = $statusMessage;
  }
}