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

namespace Kufer\KuferTools\Basis\AnwesenheitenKurs;

use Kufer\Web\Classes\Stream\ArrayStream;

abstract class AnwesenheitenUseCase extends \Kufer\KuferTools\Basis\UseCase\EinzelKursUseCase
{
  public function __construct($request)
  {
    parent::__construct($request, new AnwesenheitenResponse());
  }

  public function action()
  {
    $zeitRaum = $this->getDatumErstenUndLetztenKurstag();
    $vonDat = $this->getVonDat($zeitRaum['vonDat']);
    $bisDat = $this->getBisDat($zeitRaum['bisDat']);
    $kursTageInfo = $this->getKursTageInfo($vonDat, $bisDat);
    $belegungInfo = $this->getBelegungInfo($vonDat, $bisDat);
    $belegungInfo = $this->addAdditionalInfoToBelegungInfo($belegungInfo, $vonDat, $bisDat);
    $verhaltenInfo = $this->getVerhaltenInfo($belegungInfo, $kursTageInfo);
    $anwesenheitsInfo = $this->getAnwesenheitsInfo($vonDat, $bisDat);

    $datamodulAry = $this->getDatamodulAry($kursTageInfo, $belegungInfo, $verhaltenInfo, $anwesenheitsInfo);

    return $this->getResponse($datamodulAry, $kursTageInfo);
  }

  private function getAnwColors()
  {
    $anwGruende = $this->getHLAnwesenheitGruende();

    $result = array();
    foreach ($anwGruende as $anwGrund) {
      $result[$anwGrund->status] = $anwGrund->farbe;
    }

    return $result;
  }

  private function getDatamodulAry($kursTageInfo, $belegungInfo, $verhaltenInfo, $anwesenheitsInfo)
  {
    $result = array();
    foreach ($kursTageInfo as $ktInfo) {
      foreach ($belegungInfo as $belInfo) {
        $datamodul = new class() extends \Datamodul {
          public $ktInfo;
          public $belInfo;
          public $anwInfo;
          public $verhInfo;
          public $ignoreEintritt;
          public $ignoreAustritt;
        };

        $datamodul->ktInfo = $ktInfo;
        $datamodul->belInfo = $belInfo;

        $datamodul->anwInfo = new \Datamodul(); 
        foreach ($anwesenheitsInfo as $anwInfo) {
          if ($anwInfo->abelegid == $belInfo->belegid
              && $anwInfo->aktid == $ktInfo->id) {
            $datamodul->anwInfo = $anwInfo;
          }
        }

        $datamodul->verhInfo = new \Datamodul(); 
        foreach ($verhaltenInfo as $verhInfo) {
          if ($verhInfo->belegid == $belInfo->belegid
              && $verhInfo->ktid == $ktInfo->id) {
            $datamodul->verhInfo = $verhInfo;
            
            $datamodul->verhInfo->text = $verhInfo->text->text;
          }
        }

        $datamodul->ignoreAustritt = $this->shouldIgnoreAustrittsdatum();
        $datamodul->ignoreEintritt = $this->shouldIgnoreEintrittsdatum();

        if (!array_key_exists($belInfo->belegid, $result)) {
          $result[$belInfo->belegid] = array();
        }
        $result[$belInfo->belegid][$ktInfo->id] = $datamodul;
      }
    }

    return $result;
  }

  private function getDatumErstenUndLetztenKurstag()
  {
    static $bisDat = null;
    static $vonDat = null;

    if (is_null($bisDat)) {
      $dbwKTage = new \DBWorkKurseTageWT();
      if ($this->isDozTool()) {
        $dbwKTage->newSearch();
        $dbwKTage->toobject->nodoztool = true;
      }
      $tool0Settings = \ToolSettingsAPI::getToolSettings(0);
      $kurstageNurVonEingeloggtemDozent = $tool0Settings->kurstageNurVonEingeloggtemDozent && $this->isDozTool();
      $kurstagAry = $dbwKTage->getKurstagebyKursNR($this->request->knr, -1, $kurstageNurVonEingeloggtemDozent);
      $anzahlKurstage = count($kurstagAry);

      $bisDat = '';
      $vonDat = '';
      if ($anzahlKurstage > 0) {
        $firstKurstag = $kurstagAry[0];
        $lastKurstag = $kurstagAry[$anzahlKurstage - 1];
        $vonDat = $firstKurstag->datum;
        $bisDat = $lastKurstag->datum;
      }
    }

    return array('vonDat' => $vonDat, 'bisDat' => $bisDat);
  }

  private function getVonDat($pDefaultValue)
  {
    if (!is_null($this->request->vonDat) && $this->request->vonDat !== '') {
      $vonDat = $this->request->vonDat;
    }
    
    elseif (is_null($this->request->vonDat) && isset($this->toolSettings->anwFilterVonDatum) && $this->toolSettings->anwFilterVonDatum != '' && \DateTimeOperations::isValidDate($this->toolSettings->anwFilterVonDatum)) {
      $vonDat = $this->toolSettings->anwFilterVonDatum;
    } else {
      $vonDat = $pDefaultValue;
    }

    return $vonDat;
  }

  private function getBisDat($pDefaultValue)
  {
    if (!is_null($this->request->bisDat) && $this->request->bisDat !== '') {
      $bisDat = $this->request->bisDat;
    } else {
      $bisDat = $pDefaultValue;
    }

    return $bisDat;
  }

  private function getKursTageInfo($vonDat, $bisDat)
  {
    $dbwAnw = new \DBWorkAnwesenheit();

    return $dbwAnw->getAnwesenheitKurstagInfo($this->request->knr, $vonDat, $bisDat, false, -1, $this->isDozTool());
  }

  
  private function getBelegungInfo($vonDat, $bisDat)
  {
    if ($this->shouldIgnoreAustrittsdatum()) {
      $vonDat = false;
    }
    if ($this->shouldIgnoreEintrittsdatum()) {
      $bisDat = false;
    }

    $dbwAnw = new \DBWorkAnwesenheit();

    return $this->addFirmenInfo($dbwAnw->getAnwesenheitBelegungInfo(
      $this->request->knr,
      $this->getTnStatusAry(),
      $vonDat,
      $bisDat,
      false,
      $this->getFirmaTnr(),
      $this->getTeilnehmerTnr(),
      function(\DBWorkBelegung $dbwBelegung): \DBWorkBelegung {
        $dbwBelegung->setPersonenOrderBySettings($this->toolSettings, 'tn');

        return $dbwBelegung;
      }
    ));
  }

  
  private function addFirmenInfo(array $anwBelInfos): array
  {
    $dbwTn = \DBWorkTeilnehmer::getDefaultInstance(1, true);

    if (\DBWorkBASysSettings::isBadMergentheimFabi()) {
      
      $dbwBeziehungen = new \DBWorkBeziehung(1, true);

      return array_map(static function(\AnwesenheitsBelegungInfo $anwBelInfo) use ($dbwTn, $dbwBeziehungen) {
        $firmenBez = $dbwBeziehungen->getBeziehungMitarbeiterZuFirma($anwBelInfo->tnr);

        if (count($firmenBez) > 0) {
          $firma = $dbwTn->getTeilnehm($firmenBez[0]->nr1);
          $anwBelInfo->firma = $firma->getVarValue('name_ggf_vorname');
        }

        return $anwBelInfo;
      }, $anwBelInfos);
    } else {
      
      return array_map(static function(\AnwesenheitsBelegungInfo $anwBelInfo) use ($dbwTn) {
        $firmaTnr = $anwBelInfo->firmaId;
        if (!($firmaTnr > 0)) {
          return $anwBelInfo;
        } else {
          $firma = $dbwTn->getTeilnehm($firmaTnr);
          $anwBelInfo->firma = $firma->getVarValue('name_ggf_vorname');

          return $anwBelInfo;
        }
      }, $anwBelInfos);
    }
  }

  
  private function shouldIgnoreAustrittsdatum(): bool
  {
    return $this->toolSettings->tnIgnoreAustrittDate ?? false;
  }

  
  private function shouldIgnoreEintrittsdatum(): bool
  {
    return $this->toolSettings->tnIgnoreEintrittDate ?? false;
  }

  private function getVerhaltenInfo($belegungInfo, $ktageInfo)
  {
    $dbwAnw = new \DBWorkAnwesenheit();

    return $dbwAnw->getAnwesenheitsVerhaltenInfo($belegungInfo, $ktageInfo);
  }

  private function getAnwesenheitsInfo($vonDat, $bisDat)
  {
    $dbwAnw = new \DBWorkAnwesenheit();
    $anwInfos = $dbwAnw->getAnwesenheiten($this->request->knr, $vonDat, $bisDat, array(), -1, true, $this->getFirmaTnr());
    
    $hlAnwFarben = $this->getAnwColors();
    foreach ($anwInfos as $key => $anwInfo) {
      if (isset($hlAnwFarben[$anwInfo->astatus])) {
        $anwInfos[$key]->farbe = $hlAnwFarben[$anwInfo->astatus];
      }
      foreach ($anwInfo->_eanws as $key2 => $anwExtra) {
        $anwInfo->_eanws[$key2]->farbe = $hlAnwFarben[$anwExtra->estatus];
      }
    }

    return $anwInfos;
  }

  private function getTnStatusAry()
  {
    if (is_null($this->request->tnStatus)) {
      if ($this->toolSettings->anwFilterStatus == '') {
        return \StringOperations::str_split('APSZ'); 
      } else {
        return \StringOperations::str_split($this->toolSettings->anwFilterStatus);
      }
    }

    return $this->request->tnStatus;
  }

  private function showAnzeigeElement($pVarName)
  {
    $requestVar = $this->request->{'anzeige' . $pVarName};
    $toolSettingsVar = $this->toolSettings->{'anwFilterAnzeige' . $pVarName};

    
    return ((is_null($requestVar) && $toolSettingsVar) || (!is_null($requestVar)) && $requestVar);
  }

  private function showUhrzeit()
  {
    return $this->showAnzeigeElement('Uhrzeit');
  }

  private function showUE()
  {
    return $this->showAnzeigeElement('UE');
  }

  private function showDozent()
  {
    return $this->showAnzeigeElement('Dozent');
  }

  private function showFaecher()
  {
    return $this->showAnzeigeElement('Faecher');
  }

  private function showBemerkung()
  {
    return $this->showAnzeigeElement('Bemerkung');
  }

  private function addAdditionalInfoToBelegungInfo($pBelegungInfo, $pVonDat, $pBisDat)
  {
    $dbwAnw = new \DBWorkAnwesenheit(1, true);
    $showAnwInProzent = $this->toolSettings->useAnwInAnwKontr;
    $showAnwTage = $this->toolSettings->useAnwTageInAnwKontr;
    $showAbwTage = $this->toolSettings->useAbwInAnwKontr;
    if ($showAnwInProzent || $showAnwTage || $showAbwTage) {
      foreach ($pBelegungInfo as $belegung) {
        if ($showAnwInProzent) {
          $belegung->inProzent = $dbwAnw->getAnwProzent($belegung->belegid, $pVonDat, $pBisDat, $this->request->knr, '');
        }
        if ($showAnwTage) {
          $belegung->tageDa = $dbwAnw->getAnwTage($belegung->belegid, $pVonDat, $pBisDat, $this->request->knr, '');
        }
        if ($showAbwTage) {
          $belegung->tageWeg = $dbwAnw->getAbwTage($belegung->belegid, $pVonDat, $pBisDat, $this->request->knr, '');
        }
      }
    }

    return $pBelegungInfo;
  }

  protected function showFilterButton($sectId)
  {
    return $this->isRechtAllowed($sectId . '.0.2');
  }

  protected function getResponse($datamodulAry, $kursTageInfo)
  {
    
    $sectId = $this->getToolSectionId();
    $this->handleResponseStrategies();
    
    $this->response->kurs = $this->getKurs($this->request->knr);
    $this->response->belKtInfos = $datamodulAry;
    $this->response->kursTageInfo = $kursTageInfo;

    $this->response->showFilterButton = $this->showFilterButton($sectId);
    $this->response->zeigeUhrzeit = $this->showUhrzeit();
    $this->response->zeigeUE = $this->showUE();
    $this->response->zeigeDozent = $this->showDozent();
    $this->response->zeigeFaecher = $this->showFaecher();
    $this->response->zeigeBemerkung = $this->showBemerkung();
    $this->response->zeigeAnwInProzent = $this->toolSettings->useAnwInAnwKontr;
    $this->response->zeigeAnwTage = $this->toolSettings->useAnwTageInAnwKontr;
    $this->response->zeigeAbwTage = $this->toolSettings->useAbwInAnwKontr;
    $this->response->isBearbeitbar = $this->isBearbeitbar();
    $this->response->anwInZukunftBearbeitenErlaubt = $this->sindAnwInZukunftBearbeitbar();
    $this->response->anwVonAnderenDozentenBearbeitbar = $this->sindAnwVonAnderenDozentenBearbeitbar();

    if ($this->request->einstieg) {
      \Kufer\KuferTools\Utils\Referrer::resetReferrerInSession($this->getToolId());
    } else {
      \Kufer\KuferTools\Utils\Referrer::aktualisiereReferrerInSession($this->getToolId(), $this->request->referer, $this->request->refererLabel);
    }

    $this->response->backButtonLabel = $this->getBackButtonLabel();
    $this->response->backButtonLink = $this->getBackButtonLink($this->response->kurs->id, $this->request->belegId);

    $this->response->anwGruende = $this->getHLAnwesenheitGruende();
    $this->response->anwGruendeLegende = $this->getHLAnwesenheitGruendeLegende();
    $this->response->bearbeiterKuferTools = \ToolSettingsAPI::getToolSettings(0)->direktMaKuerzel;
    $this->response->anwesenheitenAusKuferSQLNichtBearbeitbar = $this->areAnwesenheitenAusKuferSQLNichtBearbeitbar();

    $this->response->setFilter = $this->request->setFilter;

    $this->response->xsrf = \Xsrf::getXsrfGetParameter('kurs_anw_aendern', $this->response->kurs->id);
    $this->response->statusMessageContainer = $this->request->statusMessageContainer;

    return $this->response;
  }

  protected function areAnwesenheitenAusKuferSQLNichtBearbeitbar(): bool
  {
    return false;
  }

  
  protected function getHLAnwesenheitGruende()
  {
    static $cache = null;
    if (is_null($cache)) {
      $dbw = \DBWorkHLAnwesenheitGruende::getDefaultInstance();
      $cache = $dbw->getAll();
    }

    return $cache;
  }

  
  protected function getHLAnwesenheitGruendeLegende(): array
  {
    $statusAry = array_filter(explode(',', $this->toolSettings->anwShowLegendeStatus));

    return (new ArrayStream($this->getHLAnwesenheitGruende()))
      ->filter(static function(\HLAnwesenheitGruende $grund) use ($statusAry): bool {
        if (empty($statusAry)) {
          return true; 
        } else {
          return in_array($grund->status, $statusAry);
        }
      })
      ->toArray();
  }

  protected function getBackButtonLabel()
  {
    return \Kufer\KuferTools\Utils\Referrer::getReferrerLabelFromSession($this->getToolId(), 'Zurück');
  }

  protected function getBackButtonLink($pKnr, $pBelegId)
  {
    $defaultLink = 'index.php?tool_id=' . $this->getToolId() . '&action=kursdetails&knr=' . $pKnr . ($pBelegId != '' ? '&belid=' . $pBelegId : '');

    return \Kufer\KuferTools\Utils\Referrer::getReferrerFromSession($this->getToolId(), $defaultLink);
  }

  protected function getResponseStrategies()
  {
    return array(
        new \Kufer\KuferTools\Utils\ResponseStrategies\ResponseMitRahmen($this)
    );
  }

  protected function isBearbeitbar()
  {
    return false;
  }

  protected function sindAnwInZukunftBearbeitbar()
  {
    return false;
  }

  protected function sindAnwVonAnderenDozentenBearbeitbar()
  {
    return false;
  }

  protected function getFirmaTnr()
  {
    return null;
  }

  
  protected function getTeilnehmerTnr()
  {
    return null;
  }

  protected function isDozTool()
  {
    return false;
  }
} 

class AnwesenheitenRequest
{
  public $einstieg;
  public $knr;
  public $belegId;
  public $vonDat;
  public $bisDat;
  public $tnStatus;
  public $anzeigeUhrzeit;
  public $anzeigeUE;
  public $anzeigeDozent;
  public $anzeigeFaecher;
  public $anzeigeBemerkung;
  public $referer;
  public $refererLabel;
  public $statusMessageContainer;

  public $setFilter = false;
}

class AnwesenheitenResponse extends \Kufer\KuferTools\Basis\UseCase\ToolResponse
{
  public $user;
  public $menuPunkte;
  public $kurs;
  public $belKtInfos;
  public $kursTageInfo;
  public $showFilterButton;
  public $zeigeUhrzeit;
  public $zeigeUE;
  public $zeigeDozent;
  public $zeigeFaecher;
  public $zeigeBemerkung;
  public $zeigeAnwInProzent;
  public $zeigeAnwTage;
  public $zeigeAbwTage;
  public $backButtonLabel;
  public $backButtonLink;
  public $xsrf;
  public $isBearbeitbar = false;
  public $statusMessageContainer;
  public $anwInZukunftBearbeitenErlaubt;
  public $anwVonAnderenDozentenBearbeitbar;
  public $anwGruende;
  public $anwGruendeLegende;
  public $bearbeiterKuferTools;
  public $anwesenheitenAusKuferSQLNichtBearbeitbar;
  public $setFilter;
}