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

namespace Kufer\Web\KuferTools\Basis\Anmeldung\AnmeldeFormular;

use Kufer\Web\KuferTools\Basis\Anmeldung\AnmeldeartDialog\AllowedAnmeldearten;
use Kufer\Web\KuferTools\Basis\Anmeldung\HandleAnmeldung\HandleAnmeldungUseCase;
use Kufer\Web\KuferTools\Utils\DatamodulHelper\Kurse\KursHelperFactory;

abstract class AnmeldeFormularUseCase extends \Kufer\Web\KuferTools\Basis\UseCase\ToolUseCase
{
  public function __construct($request)
  {
    parent::__construct($request, new AnmeldeFormularResponse());
  }

  abstract protected function getTeilnehmerHelper(): \Kufer\Web\KuferTools\Utils\DatamodulHelper\Teilnehmer\TeilnehmerHelper;

  public function hasAccess($pToolSectionId = null)
  {
    if (!parent::hasAccess($pToolSectionId)) {
      return false;
    }
    $this->aktualisiereKnrInSession();
    $knr = \SessionOperations::getVarValueWTIntern('anmeldung_knr', -1);
    if ($knr != -1) {
      
      
      $kurshelper = KursHelperFactory::getKursHelperByToolID(static::getToolId(), $this->toolSettings, static::getUser());
      $allowedKnrs = $kurshelper->getIdsMitFilter($this->getToolId());
      if (in_array($knr, $allowedKnrs) == false) {
        return false;
      }
    }
    $this->aktualisiereTnrInSession(null, null);
    $tnr = \SessionOperations::getVarValueWTIntern('anmeldung_tnr', -1);
    $tguid = \Kufer\Web\Classes\Addfunctions\Guid::validOrNull(\SessionOperations::getVarValueWTIntern('anmeldung_tguid', null));
    if ($tnr != -1) {
      $tnhelper = $this->getTeilnehmerHelper();
      if (!$tnhelper->isAllowed(new \Kufer\Web\Classes\Identifier\Identifier($tnr, $tguid))) {
        return false;
      }
    }

    return true;
  }

  public function action()
  {
    $newTnr = null;
    $newGuid = null;
    if ($this->request->action == 'newTeilnehmer') {
      $tnInserter = new \Kufer\Web\KuferTools\Utils\TeilnehmerHandler\TeilnehmerInserter($this->toolSettings);
      list($statusCode, $newTnr, $wrongFields) = array_values($tnInserter->handleTeilnehmerInsert($this->request->wssHandler, $this->request->columnValues));
      $this->response->newTnStatusCode = $statusCode;
      $this->response->newTnWrongFields = $wrongFields;
    }
    $this->aktualisiereKnrInSession();
    $this->aktualisiereTnrInSession($newTnr, $newGuid);
    $this->aktualisiereChoosedOptions();

    return $this->getResponse();
  }

  private function aktualisiereChoosedOptions()
  {
    if ($this->request->einstieg) {
      $this->resetChoosedOptions();
    }
  }

  private function resetChoosedOptions()
  {
    \SessionOperations::setVarValueWTIntern('choosedOptions', null);
    \SessionOperations::setVarValueIntern('kw_session_put_tools_belegungsstatus', null);
  }

  private function aktualisiereKnrInSession()
  {
    if (trim($this->request->knr) != '') {
      $knr = $this->request->knr;
    } elseif ($this->request->einstieg) {
      $knr = null;
    } else {
      $knr = \SessionOperations::getVarValueWTIntern('anmeldung_knr', null);
    }
    \SessionOperations::setVarValueWTIntern('anmeldung_knr', $knr);

    $knrBefore = \SessionOperations::getVarValueWTIntern('knr_before', null);
    if ($knrBefore != $knr) {
      $this->resetChoosedOptions();
      \SessionOperations::setVarValueWTIntern('knr_before', $knr);
    }
  }

  
  private function aktualisiereTnrInSession($newTnr, ?string $newGuid)
  {
    if ((is_numeric($this->request->tnr) && $this->request->tnr >= 0)) {
      $tnr = $this->request->tnr;
      $tguid = $this->request->tguid;
    } elseif (!is_null($newTnr) && !$this->request->keepCurrentTnr) {
      $tnr = $newTnr;
      $tguid = $newGuid;
    } elseif ($this->request->einstieg) {
      $tnr = null;
      $tguid = null;
    } else {
      $tnr = \SessionOperations::getVarValueWTIntern('anmeldung_tnr', null);
      $tguid = \SessionOperations::getVarValueWTIntern('anmeldung_tguid', null);
    }

    if (!empty($tguid) && \Kufer\Web\Classes\Addfunctions\Guid::validate($tguid)) {
      $tguid = new \Kufer\Web\Classes\Addfunctions\Guid($tguid);
    } else {
      $tguid = null;
    }

    \SessionOperations::setVarValueWTIntern('anmeldung_tnr', $tnr);
    \SessionOperations::setVarValueWTIntern('anmeldung_tguid', (string)$tguid);

    $tnrBefore = \SessionOperations::getVarValueWTIntern('tnr_before', null);
    $tguidBefore = \SessionOperations::getVarValueWTIntern('tguid_before', null);
    if ($tnrBefore != $tnr || (string)$tguidBefore !== (string)$tguid) {
      $this->resetChoosedOptions();
      \SessionOperations::setVarValueWTIntern('tnr_before', $tnr);
      \SessionOperations::setVarValueWTIntern('tguid_before', (string)$tguid);
    }
  }

  
  private function getKursDataByDMZ(): \Kurs
  {
    static $kurs = null;
    if (is_null($kurs)) {
      $kurs = $this->getKurs();
      if (isset($kurs->id) && \AnmeldevorgangAdapter::getUebermittlungsart() == ANMELDUNG_MATOOL_DMZ) {
        try {
          $kurs = \AnmeldeAPI::updateKursData($kurs);
        } catch (\Exception $e) {
          $this->response->doWarningMessage4Kurs = true;
        }
      }
    }

    return $kurs;
  }

  
  private function getKurs(): \Kurs
  {
    $knr = \SessionOperations::getVarValueWTIntern('anmeldung_knr', -1);
    $dbwKurse = new \DBWorkKurse(1, true);
    if ($knr != -1) {
      return $dbwKurse->getKurs($knr, true);
    } else {
      return $dbwKurse->getNewObject();
    }
  }

  private function getTeilnehmer(): \Teilnehmer
  {
    $tnr = \SessionOperations::getVarValueWTIntern('anmeldung_tnr', -1);
    $tguid = \SessionOperations::getVarValueWTIntern('anmeldung_tguid', null);
    if (!empty($tguid)) {
      $tguid = new \Kufer\Web\Classes\Addfunctions\Guid($tguid);
    } else {
      $tguid = null;
    }

    $dbwTeilnehmer = new \DBWorkTeilnehmer(1, true);
    if ($tnr >= 0) {
      return $dbwTeilnehmer->getTeilnehm(new \Kufer\Web\Classes\Identifier\Identifier($tnr, $tguid), true);
    } else {
      return $dbwTeilnehmer->getNewObject();
    }
  }

  private function getHlNachlassGrund(): string
  {
    $hlAnmBemerkung = new \HinterlegungAnmBemerkung();
    $hlAnmBemerkung->fields = array('grund');

    return $hlAnmBemerkung->CreateDialog('hlNachlassGrund', '#hlNachlassGrund', 'Nachlassgrund', '', '');
  }

  private function getSelectedAnmeldeForm(): string
  {
    $ausgewaehlteOptionen = \SessionOperations::getVarValueWTIntern('choosedOptions');
    if (!isset($ausgewaehlteOptionen->AnmForm)) {
      return 'maAnmeld_anmArt';
    }
    switch ($ausgewaehlteOptionen->AnmForm) {
      default:
      case 0:
        return 'maAnmeld_anmArt';
      case 1:
        return 'anmArt_elternKind';
      case 2:
        return 'anmArt_firma';
      case 4:
        return 'anmArt_mehrfach';
      case 6:
        return 'anmArt_kind';
    }
  }

  
  abstract protected function isTeilnehmerAnlegenAllowed(): bool;

  protected function getResponse()
  {
    $this->handleResponseStrategies();
    $tn = $this->getTeilnehmer();
    
    $this->response->doWarningMessage4Kurs = false;
    
    
    $kurs = $this->getKursDataByDMZ();

    $this->response->teilnehmer = $tn;
    $this->response->kurs = $kurs;
    $this->response->toolSettings = $this->toolSettings;
    $this->response->hlbemerkung = \HLDispatcher::GetHinterlegungDialog(\HLDispatcher::HL_BEMERKUNG);
    $this->response->hlNachlassGrund = $this->getHlNachlassGrund();
    $this->response->formSettings = $this->getFormularSettings($tn, $kurs);
    $this->response->tnAnlegenAllowed = $this->isTeilnehmerAnlegenAllowed();
    if (isset($tn->id)) {
      $this->response->formSettings = $this->getFormularSettings($tn, $kurs);
      $this->response->tnAngemeldet = $this->isTnAngemeldet($kurs, $tn);
      $this->response->hasSepaMandat = \StammBvAPI::hasSepaMandat($tn);
      $this->response->ermaessigung = $this->getErmaessigung($tn);
      $this->response->tnGuthaben = $this->getTnGuthaben($tn);
    }
    $this->response->tnplaetze = $this->getTnPlaetze($kurs);
    $this->response->anmeldeStatusA = !is_null($kurs->id) && (!is_null($this->request->anmeldeStatus) || $this->isAnmeldeStatusAllowed($kurs));
    $this->response->kursVoll = $kurs->isKursVoll();
    $this->response->zusaetzlicheAnmeldestatusErlaubt = $this->zusaetzlicheAnmeldestatusErlaubt();

    $this->response->anmeldeStatus = $this->request->anmeldeStatus;
    $this->response->anmForm = $this->getSelectedAnmeldeForm();
    $this->response->isAnmEndeErreicht = $this->isAnmEndeErreicht($kurs);
    $this->response->isAnmBeginnErreicht = $this->isKursBeginnErreicht($kurs);
    $this->response->isAnmBeginnErreichtNoCheck = $this->isKursBeginnErreichtNoCheck($kurs);

    $this->response->kurseProSeite = ($this->toolSettings->kurseproseite > 0) ? $this->toolSettings->kurseproseite : 20;
    $this->response->teilnehmerProSeite = ($this->toolSettings->teilnehmerproseite > 0) ? $this->toolSettings->teilnehmerproseite : 20;

    $this->response->isEinzelveranstaltung = $kurs->isEinzelveranstaltung();
    if ($this->response->isEinzelveranstaltung) {
      $this->response->normaleAnmeldungenVorhanden = $this->normaleAnmeldungenVorhanden();
    }

    $this->response->isKinderKurs50 = $kurs->isKinderKurs() && \System::isKuferSql5();
    $this->response->isKindAnmAllowedForUebermittlungsart = in_array(
      \AnmeldevorgangAdapter::getUebermittlungsart(),
      array(ANMELDUNG_MATOOL_DMZ, ANMELDUNG_MATOOL_MAIL, ANMELDUNG_MATOOL_FILE)
    );

    $allowedAnmeldearten = new AllowedAnmeldearten(
      $kurs,
      $this->response->isKinderKurs50,
      $this->response->isKindAnmAllowedForUebermittlungsart,
      $this->isRechtElternKindOderKindAnmAllowed(),
      $this->isRechtMehrfachAnmAllowed(),
      $this->isRechtFirmenAnmAllowed(),
      (bool)$this->toolSettings->filterAnmeldeartenByWeb
    );

    $this->response->anmeldungAllowed = $allowedAnmeldearten->determineAllowAnmeldung();
    $this->response->normalAnmAllowed = $allowedAnmeldearten->determineAllowNormal();
    $this->response->elternKindAnmAllowed = $allowedAnmeldearten->determineAllowElterKind();
    $this->response->kindAnmAllowed = $allowedAnmeldearten->determineAllowKind();
    $this->response->mehrfachAnmAllowed = $allowedAnmeldearten->determineAllowMehrfach();
    $this->response->faAnmAllowed = $allowedAnmeldearten->determineAllowFirmen();
    if (!$this->response->anmeldungAllowed && $this->response->formSettings) {
      $this->response->formSettings['anmeldungMoeglichStatus'] = 'kurs_anmeldung_nicht_freigegeben';
    }

    return $this->response;
  }

  abstract protected function isRechtElternKindOderKindAnmAllowed(): bool;

  abstract protected function isRechtMehrfachAnmAllowed(): bool;

  abstract protected function isRechtFirmenAnmAllowed(): bool;

  private function isAnmEndeErreicht(\Kurs $kurs): bool
  {
    
    if (isset($this->toolSettings->anmEndeErreicht) && $this->toolSettings->anmEndeErreicht) {
      return false;
    }

    return \Kufer\Web\Classes\Addfunctions\KursOperations::isAnmEndeErreicht($kurs);
  }

  protected function getFormularSettings(\Teilnehmer $pTeilnehmer, \Kurs $pKurs): array
  {
    $settings = array();
    $settings['formReadOnly'] = $this->isFormReadOnly();
    $settings['allowKinderFunktionen'] = !$settings['formReadOnly'] && \System::isKuferSql5();
    $settings['formDisabled'] = ($this->isFormReadOnly()) ? 'disabled' : '';
    $settings['anmeldeartOptions'] = $this->getAnmeldartOptions();
    $settings['anmeldeGebuehr'] = $this->getAnmeldeGebuehr($pTeilnehmer, $pKurs);
    $settings['anmeldungMoeglichStatus'] = $this->anmeldenMoeglichStatus($pTeilnehmer, $pKurs);
    $settings['newsletterAllowed'] = $this->isNewsletterAllowed();
    $settings['eintrittAllowed'] = !is_null($pKurs->id) && $this->isEintrittAllowed($pKurs);
    $settings['bemerkungAllowed'] = $this->isBemerkungAllowed();
    $settings['anmeldeartAllowed'] = $this->isAnmeldeartAllowed();
    $settings['belegungsStatusAllowed'] = $this->isBelegungsStatusAllowed();
    $settings = array_merge($settings, $this->isZahlartAllowed());
    $settings['anmeldeDetailsButton'] = $this->isAnmeldeDetailsButtonAllowed();
    $settings['abwZahlwegButton'] = $this->isAbwZahlwegButtonAllowed();
    $settings['nachlassButton'] = $this->isNachlassButtonAllowed();
    $settings['anmeldeartButton'] = $this->isAnmeldeartButtonAllowed();

    return array_merge($settings, $this->isKursDetailsAllowed($pKurs));
  }

  
  private function zusaetzlicheAnmeldestatusErlaubt(): bool
  {
    $uebermittlungsart = \AnmeldevorgangAdapter::getUebermittlungsart();

    return $uebermittlungsart == \ANMELDUNG_MATOOL_DMZ || $uebermittlungsart == \ANMELDUNG_MATOOL_ONLINE;
  }

  
  protected function isFormReadOnly(): bool
  {
    $readonly = $this->request->anmeldeStatus === HandleAnmeldungUseCase::SUCCESS_ANGEMELDET
      || $this->request->anmeldeStatus === HandleAnmeldungUseCase::SUCCESS_ANGEMELDET_UND_EMAIL_VERSANDT
      || $this->request->anmeldeStatus === HandleAnmeldungUseCase::SUCCESS_ANGEMELDET_ABER_HAUPT_TN_EMAIL_FALSCH
      || $this->request->anmeldeStatus === HandleAnmeldungUseCase::SUCCESS_ANGEMELDET_ABER_SONSTIGE_EMAIL_FEHLER
      || $this->request->anmeldeStatus === HandleAnmeldungUseCase::INFO_DOPPELT_AUFGERUFEN;
    if ($readonly) {
      \SessionOperations::setVarValueWTIntern('AnmeldungReadonly_' . $this->getToolId(), 1);
    } else {
      \SessionOperations::setVarValueWTIntern('AnmeldungReadonly_' . $this->getToolId(), 0);
    }

    return $readonly;
  }

  private function isAnmeldeStatusAllowed(\Kurs $kurs): bool
  {
    if (!(!$kurs->isKursVoll() || $this->toolSettings->ueberbuchenErlaubt && $kurs->bis_max !== 'W')) {
      return false;
    }

    if ($this->toolSettings->filterAnmeldeartenByWeb) {
      if (($kurs->webflags & \Kurs::WEBFLAG_KEINE) !== 0) {
        return false;
      }
    }

    return true;
  }

  private function getTnGuthaben(\Teilnehmer $tn): float
  {
    return \MathOperations::stringToFloat($tn->guthaben);
  }

  private function getErmaessigung(\Teilnehmer $tn): string
  {
    if ($tn->erm_grund == 0) {
      $ermaessigung = 'keine Erm&auml;&szlig;igung';
    } else {
      if ($tn->erm_proz == '' || $tn->erm_proz == 0) {
        $ermaessigung = 'kursbezogene Erm&auml;&szlig;igung';
      } else {
        $ermaessigung = \CleanOperations::cleanInt($tn->erm_proz) . ' %';
      }
      if (!\DateTimeOperations::isDateTimeEmptyOrDefault($tn->erm_ende)) {
        $ermaessigung .= ' bis ' . \CleanOperations::cleanDateString($tn->erm_ende);
      }
    }

    return $ermaessigung;
  }

  private function getTnPlaetze(\Kurs $kurs): string
  {
    
    $teilFrei = $kurs->getVarValue('teil_frei');
    if ($teilFrei == 0) {
      $frei = 'voll';
    } elseif ($teilFrei < 0) {
      $frei = 'zuviel: ' . abs($teilFrei);
    } else {
      $frei = 'frei: ' . \CleanOperations::cleanInt($teilFrei);
    }

    return $frei;
  }

  private function isTnAngemeldet(\Kurs $kurs, \Teilnehmer $tn): bool
  {
    if (!empty($kurs->id) && !empty($tn->id)) {
      $dbwBelegung = new \DBWorkBelegung();
      $belegung = $dbwBelegung->getBelegungenbyKursTeilnehmerNR($kurs->id, $tn->id);

      return count($belegung) > 0;
    }

    return false;
  }

  
  abstract protected function isAnmeldeartButtonAllowed(): bool;

  
  abstract protected function isNachlassButtonAllowed(): bool;

  
  abstract protected function isAbwZahlwegButtonAllowed(): bool;

  
  abstract protected function isAnmeldeDetailsButtonAllowed(): bool;

  
  abstract protected function isZahlartButtonAllowed(): bool;

  private function isZahlartAllowed(): array
  {
    $zahlartAllowed = $this->isZahlartButtonAllowed();
    $lastschriftChecked = '';
    $UEchecked = '';

    if ($zahlartAllowed) {
      
      switch ($this->toolSettings->zahlartAnmDefault) {
        default:
        case 0: 
          $lastschriftChecked = ' checked';
          break;
        case 1:  
          $UEchecked = ' checked';
          break;
      }
    }

    return compact('zahlartAllowed', 'lastschriftChecked', 'UEchecked');
  }

  
  abstract protected function isKursDetailsAllowed(\Kurs $pKurs): array;

  protected function getAktuelleURLRelative(): string
  {
    $url = \URL::loadCurrent();

    return $url->getUrlRelative();
  }

  
  abstract protected function isBelegungsStatusAllowed(): bool;

  
  abstract protected function isAnmeldeartAllowed(): bool;

  
  abstract protected function isBemerkungAllowed(): bool;

  
  private function isEintrittAllowed(\Kurs $kurs): bool
  {
    return \APIGebuehren::hasKursFortlaufendeGebuehren($kurs->id);
  }

  
  abstract protected function isNewsletterAllowed(): bool;

  private function anmeldenMoeglichStatus(\Teilnehmer $pTeilnehmerObj, \Kurs $pKursObj): string
  {
    if (empty($pTeilnehmerObj->id) || empty($pKursObj->id)) {
      return 'kurs_oder_tn_fehlt';
    }

    if ($pKursObj->abschluss == 'J') {
      return 'kurs_abgeschlossen';
    }
    if ($pKursObj->ausfall) {
      return 'kurs_ausgefallen';
    }
    
    
    if ($this->isAnmEndeErreicht($pKursObj)) {
      return 'kurs_anmeldeende_erreicht';
    }
    if ($this->isKursBeginnErreicht($pKursObj)) {
      return 'kurs_beginn_erreicht';
    }

    return 'anmeldung_moeglich';
  }

  private function isKursBeginnErreicht(\Kurs $kurs): bool
  {
    $checkKursBeginn = !($this->toolSettings->anmKursBeginnErreicht ?? true);
    if ($checkKursBeginn) {
      return $this->isKursBeginnErreichtNoCheck($kurs);
    } else {
      return false;
    }
  }

  private function isKursBeginnErreichtNoCheck(\Kurs $kurs): bool
  {
    if (is_null($kurs->id)) {
      return false;
    }

    if ($this->toolSettings->anmKursBeginnUhrzeit ?? false) {
      return $kurs->isKursBeginnUhrzeitErreicht(\DateTimeObj::getNow());
    }

    return $kurs->isKursBeginnErreicht(\DateTimeObj::getNow());
  }

  private function getAnmeldeGebuehr(\Teilnehmer $tnObj, \Kurs $kursObj): string
  {
    
    $gebuehr = '0,00';
    if (!empty($tnObj->id) && !empty($kursObj->id)) {
      if (!$kursObj->isKursVoll()) {
        $gebuehr = \APIGebuehren::getGebuehren($tnObj->id, $kursObj->id);
      }
    }

    return $gebuehr;
  }

  
  private function getAnmeldartOptions(): string
  {
    $isSelected = false;
    if (!isset($this->toolSettings->anmeldeArt) || $this->toolSettings->anmeldeArt == '') {
      $isSelected = true;
    }
    $standardOption = array(\HTMLOperations::createOptionTag('per ...', '', $isSelected));
    $options = \ComboboxAPI::getHinterlegungsAuswahl(\HLDispatcher::HL_ANMARTEN, array('kennz', 'text'), ' - ', 'kennz', $this->toolSettings->anmeldeArt);

    return implode('', array_merge($standardOption, $options));
  }

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

  private function normaleAnmeldungenVorhanden(): bool
  {
    $dbwBelegung = \DBWorkBelegung::getDefaultInstance(1, true);

    return count($dbwBelegung->getBelegungenbyKursNR($this->request->knr, true)) > 0;
  }
}

class AnmeldeFormularRequest
{
  public $einstieg = false;
  public $knr = '';
  public $tnr = -1;
  public $tguid;
  public $anmeldeStatus;
  public $action = '';
  public $keepCurrentTnr = false;
  public $columnValues;
  public $wssHandler;
}

class AnmeldeFormularResponse extends \Kufer\Web\KuferTools\Basis\UseCase\ToolResponse
{
  public $menuPunkte;
  public $toolSettings;
  public $user;
  public $kurs;
  public $teilnehmer;
  public $newTnStatusMsg;
  public $formSettings = array();
  public $anmeldeStatus;
  public $doWarningMessage4Kurs = false;
  public $zusaetzlicheAnmeldestatusErlaubt = false;
  public $newTnStatusCode = '';
  public $hlbemerkung;
  public $hlNachlassGrund = '';
  public $tnAngemeldet = false;
  public $hasSepaMandat = false;
  public $ermaessigung = '';
  public $tnGuthaben = 0.0;
  public $tnplaetze = '';
  public $anmeldeStatusA = false;
  public $kursVoll = false;
  public $anmForm = '';
  public $isAnmEndeErreicht = false;
  public $isAnmBeginnErreicht = false;
  public $isAnmBeginnErreichtNoCheck = false;
  public $tnAnlegenAllowed = false;
  public $isEinzelveranstaltung = false;
  public $normaleAnmeldungenVorhanden = false;

  public $kurseProSeite = 20;
  public $teilnehmerProSeite = 20;

  public $isKinderKurs50 = false;
  public $isKindAnmAllowedForUebermittlungsart = false;

  public $normalAnmAllowed;
  public $elternKindAnmAllowed;
  public $kindAnmAllowed;
  public $mehrfachAnmAllowed;
  public $faAnmAllowed;

  public $anmeldungAllowed;
}