<?php
/**
 * @copyright (c) Kufer Software GmbH, Oderstraße 7, D-84453 Mühldorf
 */

class PasstKursZuKurstageAPI
{
  public static function autoAnpassenKursdatenZuKurstagen(\Kurs $kurs, array $altNichtpassendeDaten, array $neuNichtpassendeDaten): bool
  {
    $fields = array(
      'beginn_dat',
      'ende_dat',
      'beginn',
      'ende',
      'stundenanz',
      'dauer'
    );

    $altNichtpassendeDatenFieldNames = array_map(static function(array $ary) {
      return $ary['name'];
    }, $altNichtpassendeDaten);
    $neuNichtpassendeDatenFieldNames = array_map(static function(array $ary) {
      return $ary['name'];
    }, $neuNichtpassendeDaten);

    $fields = array_filter($fields, static function(string $name) use ($altNichtpassendeDatenFieldNames, $neuNichtpassendeDatenFieldNames): bool {
      return !in_array($name, $altNichtpassendeDatenFieldNames, true)
        && in_array($name, $neuNichtpassendeDatenFieldNames, true);
    });

    $neuNichtpassendeDaten = array_filter($neuNichtpassendeDaten, static function(array $ary) use ($fields): bool {
      return in_array($ary['name'], $fields, true);
    });

    $oldKurs = clone $kurs;
    foreach ($neuNichtpassendeDaten as $field) {
      $kurs->{$field['name']} = $field['newvalue'];
    }

    try {
      $kurskorrekturApi = new \KurskorrekturAPI();

      return $kurskorrekturApi->updateKurs($kurs, $oldKurs);
    } catch (\Exception $ex) {
      \Logger::loggException($ex, 40);

      return false;
    }
  }

  
  public static function passenKursdatenZuKurstagen($pKnr)
  {
    $dbwKurse = new DBWorkKurseWT(1, true);
    $kurs = $dbwKurse->getKurs($pKnr);

    $dbwKurseTage = new DBWorkKurseTageWT(1, true);
    
    $dbwKurseTage->filterExcludeStatus();
    $dbwKurseTage->newSearch();
    $dbwKurseTage->fromobject->ausfall = 'A';

    $kurstageAry = $dbwKurseTage->getKurstageByKursNR($kurs->id);

    if (empty($kurstageAry)) {
      return array();
    }

    return array_merge(
      self::_vergleicheDatum($kurs, $kurstageAry),
      self::_vergleicheUe($kurs, $kurstageAry),
      self::_vergleicheUhrzeit($kurs, $kurstageAry),
      self::_vergleicheKursdauer($kurs, $kurstageAry)
    );
  }

  
  private static function _vergleicheDatum($pKurs, $pKurstagAry)
  {
    $result = array();

    $ersterKurstag = self::_getKurstagMitKleinstemDatum($pKurstagAry);

    if ($pKurs->beginn_dat != $ersterKurstag->datum) {
      $result[] = self::_getFieldInfo('beginn_dat', $pKurs->beginn_dat, $ersterKurstag->datum, false, true, 'val_date');
    }

    $letzterKurstag = self::_getKurstagMitGroesstemDatum($pKurstagAry);
    if ($pKurs->ende_dat != $letzterKurstag->datum) {
      $result[] = self::_getFieldInfo('ende_dat', $pKurs->ende_dat, $letzterKurstag->datum, true, true, 'val_date');
    }

    return $result;
  }

  
  private static function _getKurstagMitKleinstemDatum($pKurstageAry)
  {
    return array_reduce($pKurstageAry, function($bisherErsterKurstag, $kurstag) {
      return (DateTimeOperations::isDateBefore($bisherErsterKurstag->datum, $kurstag->datum) ? $bisherErsterKurstag : $kurstag);
    }, \ArrayOperations::firstValue($pKurstageAry));
  }

  
  private static function _getKurstagMitGroesstemDatum($pKurstageAry)
  {
    return array_reduce($pKurstageAry, function($bisherLetzterKurstag, $kurstag) {
      return (DateTimeOperations::isDateBefore($bisherLetzterKurstag->datum, $kurstag->datum) ? $kurstag : $bisherLetzterKurstag);
    }, \ArrayOperations::firstValue($pKurstageAry));
  }

  
  private static function _vergleicheUe($pKurs, $pKurstagAry)
  {
    $result = array();

    $ktUeArray = array_map(function($kurstag) {return MathOperations::stringToFloat($kurstag->ue);}, $pKurstagAry);
    $ktUeGesamt = array_sum($ktUeArray);

    if (round(MathOperations::stringToFloat($pKurs->stundenanz), 2) != round($ktUeGesamt, 2)) {
      $result[] = self::_getFieldInfo('stundenanz', $pKurs->stundenanz, MathOperations::floatToString($ktUeGesamt), true, true, 'val_float');
    }

    return $result;
  }

  
  private static function _vergleicheUhrzeit($pKurs, $pKurstagAry)
  {
    $result = array();
    $ersterKurstag = self::_getKurstagMitKleinstemDatum($pKurstagAry);

    if ($pKurs->beginn != $ersterKurstag->zeit_beg) {
      $result[] = self::_getFieldInfo('beginn', $pKurs->beginn, $ersterKurstag->zeit_beg, true, true, 'val_time');
    }

    $letzterKurstag = self::_getKurstagMitGroesstemDatum($pKurstagAry);
    if ($pKurs->ende != $letzterKurstag->zeit_ende) {
      $result[] = self::_getFieldInfo('ende', $pKurs->ende, $letzterKurstag->zeit_ende, true, true, 'val_time');
    }

    return $result;
  }

  
  private static function _vergleicheKursdauer($pKurs, $pKurstagAry)
  {
    $anzahlTage = self::_getAnzahlVerschiedenerKurstage($pKurstagAry);
    
    
    if (preg_match('/\\d+/', $pKurs->dauer)) {
      $dauer = preg_replace('/\\d+/', $anzahlTage, $pKurs->dauer, 1);
    } else {
      $dauer = $anzahlTage . ' ' . $pKurs->dauer;
    }

    $result = array();
    if ($dauer != $pKurs->dauer) {
      $result[] = self::_getFieldInfo('dauer', $pKurs->dauer, $dauer, true, true);
    }

    return $result;
  }

  private static function _getFieldInfo($pName, $pOldValue, $pNewValue, $pChangeAble = false, $pChecked = false, $pValidation = '')
  {
    return array('name' => $pName, 'oldvalue' => $pOldValue, 'newvalue' => $pNewValue, 'changeable' => $pChangeAble, 'checked' => $pChecked, 'validation' => $pValidation);
  }

  
  private static function _getAnzahlVerschiedenerKurstage($pKurstagAry)
  {
    $datumArray = ArrayOperations::mapAttribut($pKurstagAry, 'datum');

    return count(array_unique($datumArray));
  }

  
  private static function _getScriptTagAnhandFelder($pFelderAry, $pKnr)
  {
    $xsrf = new Xsrf();

    return '<script>
      <!--
        '
        . JsOperations::getDeclarationJsonBase64('KuferTools.AnzupassendeKursdaten', $pFelderAry)
        . JsOperations::getDeclarationString('KuferTools.KursdatenAnpassenXsrf', $xsrf->generateKey4Action('kursdaten_anpassen', $pKnr))
        . '
      -->
      </script>';
  }

  
  public static function getScriptTagZumAnpassenDerKursdaten($pKnr, $pToolId, $pRechte)
  {
    $result = '';

    if (!isset($pRechte['kurs_bearbeiten']) || !ToolsAPI::rechteOr($pRechte['kurs_bearbeiten'], $pToolId)) {
      return '';
    }

    
    $felderAry = self::passenKursdatenZuKurstagen($pKnr);

    foreach ($felderAry as $key => $feld) {
      $pruefeBearbeitbarInSicht = true;
      if (!isset($feld['name']) || !ToolsAPI::rechteOr($pRechte[$feld['name']], $pToolId, $pruefeBearbeitbarInSicht)) {
        unset($felderAry[$key]);
      }
    }
    if (count($felderAry) > 0) {
      
      $felderAry = array_values($felderAry);
      $result .= self::_getScriptTagAnhandFelder($felderAry, $pKnr);
    }

    return $result;
  }

  
  public static function updateKurs($pToUpdate, $pKurs)
  {
    $isResponsive = \SessionOperations::isKuferToolsResponsive();
    if (!$isResponsive && Xsrf::KEY_OK != Xsrf::checkAndUseXsrfFromGet('kursdaten_anpassen', $pKurs->id)) {
      return false;
    }

    $origKurs = clone($pKurs);

    $whiteList = array('beginn_dat', 'ende_dat', 'stundenanz', 'beginn', 'ende', 'dauer');
    if ($isResponsive) {
      $whiteList = \array_merge($whiteList, array('bearbeiter'));
    }
    foreach ($pToUpdate as $dat) {
      if (in_array($dat->name, $whiteList) && $dat->checked) {
        $pKurs->{$dat->name} = $dat->newvalue;
      }
    }

    $kkapi = new KurskorrekturAPI();

    return $kkapi->updateKurs($pKurs, $origKurs);
  }

  

  
  private static function isRechtAllowed(string $pRecht, int $pToolId, \Benutzer $pUser): bool
  {
    return \SecurityOperations::privilegAllowed($pUser->getIdentifier(), $pToolId, $pRecht) >= 2;
  }

  public static function getRechte4KursBearbeitenMitarbeiter(int $pToolId, \Benutzer $pUser): array
  {
    return self::getRechte4KursBearbeiten($pToolId, 432, $pUser);
  }

  public static function getRechte4KursBearbeitenDozent(int $pToolId, \Benutzer $pUser): array
  {
    return self::getRechte4KursBearbeiten($pToolId, 11, $pUser);
  }

  public static function getRechte4KursBearbeitenVeranstalter(int $pToolId, \Benutzer $pUser): array
  {
    return self::getRechte4KursBearbeiten($pToolId, 621, $pUser);
  }

  private static function getRechte4KursBearbeiten(int $pToolId, int $pToolsectionKursBearbeiten, \Benutzer $pUser): array
  {
    
    return array(
      'beginn' => self::isRechtAllowed($pToolsectionKursBearbeiten . '.16', $pToolId, $pUser),
      'ende' => self::isRechtAllowed($pToolsectionKursBearbeiten . '.17', $pToolId, $pUser),
      'beginn_dat' => self::isRechtAllowed($pToolsectionKursBearbeiten . '.3', $pToolId, $pUser),
      'ende_dat' => self::isRechtAllowed($pToolsectionKursBearbeiten . '.4', $pToolId, $pUser),
      'stundenanz' => self::isRechtAllowed($pToolsectionKursBearbeiten . '.38', $pToolId, $pUser),
      'dauer' => self::isRechtAllowed($pToolsectionKursBearbeiten . '.10', $pToolId, $pUser)
    );
  }
}