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


abstract class DBWorkDblOptin extends DBWork
{
  protected $fields;

  public function __construct($pDBTyp = 1, $pNewInstance = false)
  {
    parent::__construct($pDBTyp, $pNewInstance);
    $this->fields = array('optin', 'bearbdatum', 'status', 'bemerkung', 'email', 'emailhash', 'name', 'vorname',
                          'geschlecht', 'zusatz', 'zusatz2', 'zusatz3', 'strasse', 'ort', 'tel', 'mobil', 'tel2',
                          'fax', 'krit1', 'krit2', 'krit3', 'krit4', 'krit5', 'krit6', 'feature', 'salt', 'passwort',
                          'hashversion', 'passworttext', 'dse_unterschrieben_datum', 'gebdat', 'sozarbeitgeber',
                          'name_titel', 'weitermeldecode_id');
    $this->select = implode(', ', $this->fields);
    
    $this->select = str_replace(
      array(', bemerkung', ', passworttext'),
      array(', ' . $this->clob('bemerkung'), ', ' . $this->clob('passworttext')),
      $this->select
    );
  }

  abstract protected function getFeature();

  public function getSQLValue($fieldname, $datamodul)
  {
    switch ($fieldname) {
      case 'bearbdatum':
        return $this->datetimeop->getFormatDateTime4Server($datamodul->getVarValue($fieldname));
      default:
        return parent::getSQLValue($fieldname, $datamodul);
    }
  }

  
  public function getNewObject()
  {
    return new WebDblOptin();
  }

  public function getTableName(): string
  {
    return 'web_dbloptin';
  }

  
  public function getCurrentRow($pRefreshCache = false)
  {
    $result = $this->getNewObject();

    $result->id = $this->getDatamodulValue('id');

    foreach ($this->fields as $varName) {
      $result->{$varName} = $this->getDatamodulValue($this->translateVarName($varName));
    }

    return $result;
  }

  
  public function getDblOptinByOptin($pOptin)
  {
    $sql = 'SELECT ' . $this->select . ' FROM web_dbloptin WHERE optin = \'' . $pOptin . "' AND feature = " . $this->getFeature();
    $this->dboperation->clear();
    $this->dboperation->query($sql);
    if ($this->dboperation->rowcount() == 0) {
      return null;
    }

    return $this->getFirstRow();
  }

  
  public function getDblOptinByOptinIgnoreFeature($pOptin)
  {
    $sql = 'SELECT ' . $this->select . ' FROM web_dbloptin WHERE optin = \'' . $pOptin . "'";
    $this->dboperation->clear();
    $this->dboperation->query($sql);
    if ($this->dboperation->rowcount() == 0) {
      return null;
    }

    return $this->getFirstRow();
  }

  public const MAX_OPTIN_CODE_GEN_RETRIES = 100;

  protected function getOptinCode($pDblOptin)
  {
    $i = 0;
    do {
      $optin = md5($pDblOptin->getVarValue('email') . $pDblOptin->getVarValue('bearbdatum') . 'nl' . \SecurityOperations::generateSalt());
    } while ($this->istOptinVergeben($optin) && $i++ < self::MAX_OPTIN_CODE_GEN_RETRIES);

    if ($i == self::MAX_OPTIN_CODE_GEN_RETRIES) {
      throw new \RuntimeException('Irgendwas scheint mit dem Zufallsgenerator falsch zu laufen');
    }

    return $optin;
  }

  public function saveDblOptin($pDblOptin)
  {
    $struktur = implode(', ', $this->fields);

    $optin = $this->getOptinCode($pDblOptin);
    $pDblOptin->optin = $optin;
    $pDblOptin->feature = $this->getFeature();
    $pDblOptin->emailhash = md5($pDblOptin->getVarValue('email'));

    $werte = array();
    foreach ($this->fields as $field) {
      $werte[] = $this->getSQLValue($field, $pDblOptin);
    }

    $werte = implode(', ', $werte);
    $sql = 'INSERT INTO web_dbloptin (' . $struktur . ') values (' . $werte . ');';

    
    $this->dboperation->clear();
    $this->dboperation->execute($sql);

    return $optin;
  }

  
  public function deleteOldOptinsIgnoreFeature($pDays)
  {
    $today = $this->datetimeop->getDateNow();
    $newDate = $this->datetimeop->getDateDaysBefore($today, $pDays);
    $sql = 'SELECT ' . $this->select . ' FROM web_dbloptin WHERE bearbdatum < ' . $this->datetimeop->getFormatDate4Server($newDate);
    $this->dboperation->clear();
    $this->dboperation->query($sql);
    if ($this->dboperation->rowcount() == 0) {
      return true;
    }

    $oldOptins = $this->getAllRows();

    foreach ($oldOptins as $optin) {
      $this->deleteByOptinIgnoreFeature($optin->optin);
    }

    return $this->countOldOptinsIgnoreFeature($pDays) == 0;
  }

  
  public function countOldOptinsIgnoreFeature($pDays)
  {
    $today = $this->datetimeop->getDateNow();
    $newDate = $this->datetimeop->getDateDaysBefore($today, $pDays);
    $sql = 'select count(*) as anzahl from web_dbloptin where bearbdatum < ' . $this->datetimeop->getFormatDate4Server($newDate);
    $this->dboperation->clear();
    $this->dboperation->query($sql);
    if ($this->dboperation->rowcount() == 0) {
      return 0;
    }
    $this->dboperation->selectrow(0);

    return $this->getDatamodulValue('anzahl');
  }

  
  public function deleteByName(string $pName): void
  {
    $builder = $this->getSelectQueryBuilder();
    $builder = $builder->select($this->select)
      ->from('web_dbloptin')
      ->and('feature = :feature:')
      ->and('name = :name:')
      ->paramInt('feature', $this->getFeature())
      ->paramString('name', $pName);

    $this->dboperation->clear();
    $this->dboperation->query($builder->getSQL());

    $optins = $this->getAllRows();
    foreach ($optins as $optin) {
      $this->deleteByOptin($optin->optin);
    }
  }

  
  public function deleteByOptin($pOptin)
  {
    $sql = "DELETE FROM web_dbloptin WHERE optin='$pOptin' AND feature = " . $this->getFeature();
    $this->dboperation->clear();
    $this->dboperation->execute($sql);

    $this->afterDeleteHook($pOptin);
  }

  
  public function deleteByOptinIgnoreFeature($pOptin)
  {
    $sql = "DELETE FROM web_dbloptin WHERE optin='$pOptin'";
    $this->dboperation->clear();
    $this->dboperation->execute($sql);

    $this->afterDeleteHook($pOptin);
  }

  protected function afterDeleteHook($pOptin)
  {
    
  }

  
  protected function istOptinVergeben($pOptin)
  {
    $sql = 'SELECT count(*) anzahl FROM web_dbloptin where optin=\'' . $pOptin . '\' AND feature = ' . $this->getFeature();
    $this->dboperation->clear();
    $this->dboperation->query($sql);
    $this->dboperation->selectrow(0);

    return $this->getDatamodulValue('anzahl') > 0;
  }
}