<?php


abstract class StornoMode
{
  const HINDERUNG_STATUS_PASST_NICHT = 0;
  const HINDERUNG_BETRIEBSART_PASST_NICHT = 1;
  const HINDERUNG_STATUS_NICHT_ANGEMELDET = 2;
  
  const HINDERUNG_KURS_BEREITS_BEGONNEN = 3;
  const HINDERUNG_HAT_ZAHLUNGEN = 4;
  const HINDERUNG_TEIL_EINER_MEHRFACHANMLEDUNG = 5;
  const HINDERUNG_TEIL_EINER_ELTERN_KIND_ANMELDUNG = 6;
  const HINDERUNG_ANMELDESCHLUSS_ERREICHT = 7;
  const HINDERUNG_MIN_TN_ANZAHL_WIRD_UNTERSCHRITTEN = 8;
  const HINDERUNG_HAT_ZAHLUNGEN_KIND = 9;
  const HINDERUNG_NICHT_KOMPLETT_STORNO = 10;
  const HINDERUNG_KEIN_KIND_STORNO = 11;

  const SEND_ERROR = 0;
  
  const SEND_SUCCESSFUL_PER_DIREKT = 1;
  const SEND_SUCCESSFUL_PER_DMZ = 2;
  const SEND_SUCCESSFUL_PER_EMAIL = 3;
  
  const STORNO_EMAIL = 3;
  const STORNO_DIREKT = 2;
  const STORNO_DMZ = 1;
  
  protected $kindBelegungen = array();
  protected $komplettStorno = false;
  protected $toolSettings = '';
  
  protected $hinderungsGruendeAuto = array();
  
  
  protected $status = 'S';
  
  protected $stornogrund;
  
  protected $austritt;
  
  abstract public function doStornoDMZBetrieb($pBelegung);
  abstract public function doStornoDirektBetrieb($pBelegung);
  abstract public function doStornoMailBetrieb($pBelegung);
  
  
  public function __construct($pToolSettings, $pKindBelegungen, $pKomplettStorno, $pStornoGrund) 
  {
    $this->toolSettings = $pToolSettings;
    $this->kindBelegungen = $pKindBelegungen;
    $this->komplettStorno = $pKomplettStorno;
    $this->stornogrund = $pStornoGrund;
    $this->status = 'S';
    $this->austritt = DateTimeOperations::getDateNow();;
  }
  
  
  
  public function doStorno($pOperationMode, $pBelegung) {
    switch ($pOperationMode) {
      case self::STORNO_DMZ: 
        $statusCode = $this->doStornoDMZBetrieb($pBelegung);
    
        
        return $statusCode;
      case self::STORNO_DIREKT: 
        $statusCode = $this->doStornoDirektBetrieb($pBelegung);
        
        return $statusCode;  
      case self::STORNO_EMAIL: 
        $allgSettings = AllgSettingsAPI::getAllgSettings();
        $statusCode = $this->doStornoMailBetrieb($pBelegung);
        
        return $statusCode;  
    }
    
  } 
  
  
  public static function getStornoModus($pStornoSuccess) {
    
   
    $modus = floor ($pStornoSuccess/10) % 10;
    return $modus;
  }
  
  
  
  public static function isStornoPerMail($pStornoSuccess) {
    
    $art = $pStornoSuccess % 10;
    if ($art === 3) {
      return true;
    }
    return false;
  }
  
   
  public function getHinderungsGruende($pBelegung, $pIsAutomatisch = false)
  {
    $gruende = array();
    
    
    
    $autoSuffix = '';
    $stornoMinTNanzahlPruefen = 'stornoMinTNanzahlPruefen';
    if ($pIsAutomatisch) {
      $autoSuffix = 'Auto';
      $stornoMinTNanzahlPruefen .= $autoSuffix;
    }
    
    
    
    $minTNanzahlUnterschrittenPruefen = (isset($this->toolSettings->$stornoMinTNanzahlPruefen)) ? $this->toolSettings->$stornoMinTNanzahlPruefen == 1 : true;

    
    
    
    $statusAllowed = PhpOperations::getIfIsset($this->toolSettings, 'storno_status_allowed');
    
     
    if(trim($statusAllowed) === '') {
      
      if(!$this->_isStatusAngemeldet($pBelegung) && !$this->_isStatusWarteliste($pBelegung)) {
        $gruende[] = $this->getGrundObject(self::HINDERUNG_STATUS_NICHT_ANGEMELDET);
      }
    }
    else {
      if(!$this->checkBelegungsStatus($pBelegung, $statusAllowed)) {
        $gruende[] = $this->getGrundObject(self::HINDERUNG_STATUS_PASST_NICHT);
      }
    }

    
    if($this->_isTeilEinerMehrfachAnmeldung($pBelegung)) {
      $gruende[] = $this->getGrundObject(self::HINDERUNG_TEIL_EINER_MEHRFACHANMLEDUNG);
    }
    
    
    if($this->_isTeilEinerElternKindAnmeldung($pBelegung)) {
      $gruende[] = $this->getGrundObject(self::HINDERUNG_TEIL_EINER_ELTERN_KIND_ANMELDUNG);
    }
    
    
    if($minTNanzahlUnterschrittenPruefen) {
      if($this->_wirdMinTnAnzahlUnterschritten($pBelegung)) {
          $gruende[] = $this->getGrundObject(self::HINDERUNG_MIN_TN_ANZAHL_WIRD_UNTERSCHRITTEN);
        }
    }
    
     
    

    $specialgruende = $this->getSpecialHinderungsGruende($pBelegung, $pIsAutomatisch);
    
    $kindgruende = $this->getSingleKindGruende($pIsAutomatisch);
    $gruende = array_merge($gruende, $specialgruende,$kindgruende);
   
    
    
    return $gruende;
  } 
  
  
  protected function getSingleKindGruende($pIsAutomatisch) {
    return array();
  }
  
  
  
  protected function getSpecialHinderungsGruende($pBelegung, $pIsAutomatisch = false) {
    
    
    
    
    
    
    
    $nurTeilnehmerAufWartelisteStornieren = $this->haveBelegungenNurStatusW($pBelegung);
    $gruende = array(); 
    
    if(!$nurTeilnehmerAufWartelisteStornieren) {
      
      if (!$this->komplettStorno && $pIsAutomatisch) {
         $gruende[] = $this->getGrundObject(self::HINDERUNG_NICHT_KOMPLETT_STORNO);
       }

       
       if($this->_hasZahlungen($pBelegung)) {
         $gruende[] = $this->getGrundObject(self::HINDERUNG_HAT_ZAHLUNGEN);
       }

       
       if($this->_isAnmeldeschlussErreicht($pBelegung)) {
         $gruende[] = $this->getGrundObject(self::HINDERUNG_ANMELDESCHLUSS_ERREICHT);
       }

       
       
       
       if ($pIsAutomatisch) {
         if($this->_hatKursBegonnen($pBelegung)) {
          $gruende[] = $this->getGrundObject(self::HINDERUNG_KURS_BEREITS_BEGONNEN);
         }
       }
       
       
    } 
     return $gruende;
    
  } 
  
 
  
  protected static function getGrundObject($pGrundId, $pAddInfo = null) {
    $grundObj = new stdClass();
    $grundObj->id = $pGrundId;
    $grundObj->addInfo = $pAddInfo;
    return $grundObj;
  }
  

  
  protected function _hatKursBegonnen($pBelegung)
  {
    if ($pBelegung->kurs->beginn_dat != '') {
      if (\DateTimeOperations::isDatebeforeNow($pBelegung->kurs->beginn_dat)) {
        return true;
      }
    }
    return false;
  }
  
  
  public function getHinderungsGruendeAutomatischStornieren($pBelegung)
  {
     
    
    $gruende = $this->getHinderungsGruende($pBelegung, true);
    
    
    
    if( !SessionOperations::isDmzBetrieb() ) {
      $gruende[] = $this->getGrundObject(self::HINDERUNG_BETRIEBSART_PASST_NICHT);
    }

    
    $this->hinderungsGruendeAuto = $gruende;
    return $gruende;
  }
  
  
 
  protected static function _getEMailBetreff($pBelegung, $pSprachsettings)
  {
    return 'Abmeldung von '.$pBelegung->teilnehmer->namevorname .' von '
                  .$pSprachsettings->Kurs['Singular_mit_Artikel']['Dativ'].' '.$pBelegung->knr. ' ('.$pBelegung->kurs->kurzbez_titel.')';
  }
  
  
  protected static function checkBelegungsStatus($pBelegung, $pAllowedStati)   {
    if(trim($pAllowedStati) === '') {
      return true;
    }
    $status = trim($pBelegung->status) != '' ? $pBelegung->status : 'A';
    return StringOperations::stripos($pAllowedStati, $status) !== false;
  }
  
  
  
  public function getText4HinderungsKonstanten($pHinderungsgrund ,$pBelegung, $pSprachsettings = null)
  {
    if (is_null($pSprachsettings)) {
      $sprachsettings = new SprachSettingsObject();
    }
    else 
      $sprachsettings = $pSprachsettings;
    
    $text = '';
    switch($pHinderungsgrund->id) {
      
      case self::HINDERUNG_BETRIEBSART_PASST_NICHT: 
      {
        $text = 'In der eingestellten Betriebsart (Direktbetrieb oder reiner Replikatbetrieb) ist nur Storno per E-Mail möglich. '
                . 'Ein automatisches Stornieren kann nur im DMZ-Betrieb durchgeführt werden. ';       
        break;
      }
      case self::HINDERUNG_STATUS_NICHT_ANGEMELDET:
      {
        $text = ucfirst($sprachsettings->Teilnehmer['Singular_mit_Artikel']['Nominativ']).
                ' ist nicht mit Status angemeldet (A) in '.$sprachsettings->Kurs['Singular_mit_Artikel']['Dativ'];
        break;
      }
      case self::HINDERUNG_KURS_BEREITS_BEGONNEN:
      {
        $text = ucfirst($sprachsettings->Kurs['Singular_mit_Artikel']['Nominativ']).' hat bereits am '.$pBelegung->kurs->beginn_dat.' begonnen';
        break;
      }
      case self::HINDERUNG_HAT_ZAHLUNGEN:
      {
        $text = 'Aufgrund bereits erfolgter Zahlungen/Rechnungen ist eine automatische Stornierung nicht möglich.';
        break;
      }
      case self::HINDERUNG_TEIL_EINER_MEHRFACHANMLEDUNG:
      {
        $text = ucfirst($sprachsettings->Teilnehmer['Singular_mit_Artikel']['Nominativ']).' gehört zu einer Mehrfach- oder Firmenanmeldung';
        break;
      }
      case self::HINDERUNG_TEIL_EINER_ELTERN_KIND_ANMELDUNG:
      {
        $text = 'Zu dieser Anmeldung gehören Kinderanmeldungen';
        break;
      }
      case self::HINDERUNG_ANMELDESCHLUSS_ERREICHT:
      {
        $text = 'Der Anmeldeschluss ist bereits erreicht ('.$pBelegung->kurs->anm_ende.')';
        break;
      }
      case self::HINDERUNG_MIN_TN_ANZAHL_WIRD_UNTERSCHRITTEN:
      {
        $text = $this->getText4MinTNZahlUnterschritten($pBelegung);
        break;
      }
      case self::HINDERUNG_HAT_ZAHLUNGEN_KIND:
      {
        $name = $pHinderungsgrund->addInfo['name'];
        $text = 'Aufgrund bereits erfolgter Zahlungen/Rechnungen bei '.$name.' (Teiln. Nr: '.$pHinderungsgrund->addInfo['tnr'].' )'.
          ' ist eine automatische Stornierung nicht möglich.';
        break;
      }
      case self::HINDERUNG_NICHT_KOMPLETT_STORNO:
      {
        $text = 'Es wurden nicht alle Kinder zum Stornieren ausgewählt. Eine Abmeldung ist daher nicht möglich';
        break;
      }
      case self::HINDERUNG_KEIN_KIND_STORNO:
      {
        $text = 'Es wurde kein Kind zum Stornieren ausgewählt. Eine Abmeldung ist daher nicht möglich';
        break;
      }
    }
    return $text;
  } 
  
  
  protected function getText4MinTNZahlUnterschritten($pBelegung) {
    return 'Durch eine Abmeldung würde die Mindestteilnehmerzahl unterschritten (minimal '.$pBelegung->kurs->teil_min
                .' - derzeit '.$pBelegung->kurs->anmeldungen.')';
  }
  
  
  
  
  protected static function _isStatusAngemeldet($pBelegung)
  {
    return in_array($pBelegung->status, array('A', ' ', ''));
  }    
  
  
  protected static function _isStatusWarteliste($pBelegung)
  {
    return $pBelegung->status === 'W';
  }    
  
  
  protected  static function _hasZahlungen($pBelegung)
  {
    $dbwZahlung = new DBWorkZahlung();
    return !$dbwZahlung->isStornoBzglZahlungOk($pBelegung->id);
  }
  
  
  protected static function _isTeilEinerMehrfachAnmeldung($pBelegung)
  {
    $dbwBelegung = new DBWorkBelegung(1, true);
    return $dbwBelegung->isTeilEinerMehrfachAnmeldung($pBelegung->id);
  }
  
   
  protected static function _isTeilEinerElternKindAnmeldung($pBelegung)
  {
    $dbwKinder = new DBWorkKinder(1, true);
    return (count($dbwKinder->getKinderbyBelegung($pBelegung->id))>0);
  }
  
  
  protected static function _isAnmeldeschlussErreicht($pBelegung)
  {
    if ($pBelegung->kurs->anm_ende != '') {
      $anmende = DateTimeOperations::getTimestampByDatestring($pBelegung->kurs->anm_ende);
      $akttime = gmmktime(0,0,0);
      if ($anmende < $akttime) {
        $kursbeginndat = $pBelegung->kurs->beginn_dat;
        if ($kursbeginndat !== '') {
          $kursbeginn = DateTimeOperations::getTimestampByDatestring($kursbeginndat);
          if ($kursbeginn < $akttime) {
            return true;
          }
        }
      }
    }
    return false;
  }
  
   
  protected function _wirdMinTnAnzahlUnterschritten($pBelegung)
  {
    return ($pBelegung->kurs->anmeldungen <= $pBelegung->kurs->teil_min);
  }
 
  
  
  protected function haveBelegungenNurStatusW($pBelegung)
  {
   return $pBelegung->status === 'W';
  }

  
}