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


abstract class GebuehrenElementRechner
{
  
  protected $gebuehrenElement;

  
  abstract public function ladeGebuehren($knr);

  abstract protected function getKindGebuehrElement($lfdNr, $zpid): GebuehrenElement;

  abstract protected function getKindGebuehrElementErmaessigt($lfdNr, KursgebuehrBerechnungsKontextTeilnehmer $kGebBerKontextTn): GebuehrenElement;

  
  public static function createInstance($isKuferSql5): GebuehrenElementRechner
  {
    if ($isKuferSql5) {
      return new GebuehrenElementRechnerFuenfNull();
    } else {
      return new GebuehrenElementRechnerVierZwanzig();
    }
  }

  public function setGebuehrenElement($gebuehrenElement)
  {
    $this->gebuehrenElement = $gebuehrenElement;
  }

  public function getGebuehrenSummeErmaessigt(int $currentTnIndex, KursgebuehrBerechnungsKontext $kGebBerKontext): float
  {
    $gebElem = $this->applyGebuehrenElementVisitors(clone $this->gebuehrenElement, $currentTnIndex, $kGebBerKontext);

    return $gebElem->getSum();
  }

  public function getGebuehrenSaetzeErmaessigt(int $currentTnIndex, KursgebuehrBerechnungsKontext $kGebBerKontext): array
  {
    $gebElem = $this->applyGebuehrenElementVisitors(clone $this->gebuehrenElement, $currentTnIndex, $kGebBerKontext);
    $gebElem->accept(new GebuehrenElementVisitorFloatToString());

    return $gebElem->getGebuehrensaetze();
  }

  public function getKindGebuehrSumme($lfdNr, $zpid): float
  {
    return $this->getKindGebuehrElement($lfdNr, $zpid)->getSum();
  }

  public function getKindGebuehrSaetze($lfdNr, $zpid): array
  {
    $gebElem = $this->getKindGebuehrElement($lfdNr, $zpid);
    $gebElem->accept(new GebuehrenElementVisitorFloatToString());

    return $gebElem->exportGebuehrensaetze();
  }

  public function getKindGebuehrErmaessigtSumme($lfdNr, KursgebuehrBerechnungsKontextTeilnehmer $kGebBerKontextTn): float
  {
    return $this->getKindGebuehrElementErmaessigt($lfdNr, $kGebBerKontextTn)->getSum();
  }

  public function getKindGebuehrErmaessigtSaetze($lfdNr, KursgebuehrBerechnungsKontextTeilnehmer $kGebBerKontextTn): array
  {
    $gebElem = $this->getKindGebuehrElementErmaessigt($lfdNr, $kGebBerKontextTn);
    $gebElem->accept(new GebuehrenElementVisitorFloatToString());

    return $gebElem->exportGebuehrensaetze();
  }

  
  protected function applyGebuehrenElementVisitors(GebuehrenElement $gebElem, int $currentTnIndex, KursgebuehrBerechnungsKontext $kGebBerKontext): GebuehrenElement
  {
    $zahlplan = $kGebBerKontext->tns[$currentTnIndex]->zahlplan;
    $visitKeinZp = new GebuehrenElementVisitorFilterByZahlplan($zahlplan);
    $gebElem->accept($visitKeinZp);
    if ($kGebBerKontext->isKollegenrabattApplicable($currentTnIndex)) {
      $visitKollegenRabatt = new GebuehrenElementVisitorApplyKollegenrabatt();
      $gebElem->accept($visitKollegenRabatt);
    }

    
    
    
    
    if ($currentTnIndex > 0 && ($kGebBerKontext->hauptTnAuch || $kGebBerKontext->isFirmenAnmeldung)) {
      $visitPauschal = new GebuehrenElementVisitorRemovePauschalgebuehr();
      $gebElem->accept($visitPauschal);
    }

    
    if (!$kGebBerKontext->rabattierbar) {
      $kontextTn = $kGebBerKontext->tns[$currentTnIndex];
      $visitProz = new GebuehrenElementVisitorApplyErmaessigungProz(
        $kontextTn->ermProzent,
        $kontextTn->kursbezogeneErmaessigung,
        $kontextTn->ermGrund
      );
      $gebElem->accept($visitProz);
    }

    if ($currentTnIndex == 0 && isset($kGebBerKontext->spendeninfos)) {
      $visitSpendenBetrag = new GebuehrenElementVisitorSpendenBetrag($kGebBerKontext->spendeninfos);
      $gebElem->accept($visitSpendenBetrag);
    }

    if (!$kGebBerKontext->brutto) {
      $visitNetto = new GebuehrenElementVisitorNetto();
      $gebElem->accept($visitNetto);
    }

    return $gebElem;
  }
}