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

namespace Kufer\KuferTools\Utils\LDAP;

class NeuesTnLoginAnlegen
{
  private $undoByError = array();

  public const NEUESLOGIN_SUCCESS = 1;
  public const NEUESLOGIN_ERROR_ALLGEMEIN = 2;
  public const NEUESLOGIN_ERROR_LOGIN_BEREITS_VORHANDEN = 3;
  public const NEUESLOGIN_ERROR_OPTIN_NICHT_GEFUNDEN = 4; 

  public function neuesTeilnehmerLoginperDmz($pLogin, $pTitel, $pName, $pVorname, $pPasswortHash, $pHashversion, $pEmail, $pSchulNr, $auth_extern = 0)
  {
    $login = \StringOperations::strtoupper($pLogin);

    if (\DBWorkUser::getDefaultInstance()->loginExists($login)) {
      return self::NEUESLOGIN_ERROR_LOGIN_BEREITS_VORHANDEN;
    }

    $teilnehmer = $this->insertTeilnehmer($pTitel, $pName, $pVorname, $pEmail, $pSchulNr);
    $webUser = $this->insertWebUser($login, $teilnehmer->id);

    $message = $this->getXml4Dmz($teilnehmer, $webUser);

    try {
      $abgleichAPI = new \AbgleichAPI();
      $dmzResult = $abgleichAPI->sendeNachricht(
        \AbgleichAPI::ABGLEICH_NEUES_TNLOGIN,
        new \Nutzlast($message)
      );
      if ($dmzResult->code != \AbgleichApiResult::CODE_SUCCESS) {
        $this->rewindNeusLogin();

        return self::NEUESLOGIN_ERROR_ALLGEMEIN;
      }

      $result = \JsonOperations::getFromString($dmzResult->reason);
      if (is_null($result) || !isset($result->loginWarBereitsVergeben) || !isset($result->teilnehmerWurdeNeuAngelegt) || !isset($result->technischerFehler)) {
        $this->rewindNeusLogin();

        return self::NEUESLOGIN_ERROR_ALLGEMEIN;
      }

      if ($result->loginWarBereitsVergeben) {
        
        $this->rewindNeusLogin();

        return self::NEUESLOGIN_ERROR_LOGIN_BEREITS_VORHANDEN;
      } elseif ($result->technischerFehler) {
        $this->rewindNeusLogin();

        return self::NEUESLOGIN_ERROR_ALLGEMEIN;
      } else {
        if (!$result->teilnehmerWurdeNeuAngelegt) {
          $teilnehmer = $this->getTeilnehmerObj($pTitel, $pName, $pVorname, $pEmail, '');
          $teilnehmerFromDb = $this->getTeilnehmerFromDb($teilnehmer);
          if ($teilnehmerFromDb != null && $teilnehmerFromDb->id > 0) {
            
            
            $this->rewindNeusLogin();
            $webUser = $this->insertWebUser($login, $teilnehmerFromDb->id);
          }
        }

        $this->insertWebToolsUsers($webUser->id);
        $this->insertPasswort($webUser, $pPasswortHash, $pHashversion, $auth_extern);

        return self::NEUESLOGIN_SUCCESS;
      }
    } catch (\AbgleichApiException $aae) {
      \Logger::logg('Neues Teilnehmerlogin anlegen per DMZ - folgende Exception ist aufgetreten: ' . $aae->getMessage() . "\n", 200);
      $this->rewindNeusLogin();

      return self::NEUESLOGIN_ERROR_ALLGEMEIN;
    }
  }

  
  private function getXml4Dmz($teilnehmer, $webUser)
  {
    $tnXml = $teilnehmer->ToXml(array(), true, array(), 'teilnehmer');
    $webUserXml = $webUser->ToXml(array(), true, array(), 'web_user');
    $message = new \XMLNode('neues_tn_login');
    $message->addChild($tnXml);
    $message->addChild($webUserXml);

    return $message;
  }

  private function insertTeilnehmer($pTitel, $pName, $pVorname, $pEmail, $pSchulNr)
  {
    $teilnehmer = $this->getTeilnehmerObj($pTitel, $pName, $pVorname, $pEmail, $pSchulNr);
    $undoableInsertTeilnehmer = $this->getUndoableInsertTeilnehmer($teilnehmer);
    $teilnehmerFromDb = $undoableInsertTeilnehmer->doOnce();
    $this->undoByError[] = $undoableInsertTeilnehmer;

    return $teilnehmerFromDb;
  }

  private function getTeilnehmerObj($pTitel, $pName, $pVorname, $pEmail, $pSchulNr)
  {
    $teilnehmer = new \Teilnehmer();
    $teilnehmer->setValue2Var('name_titel', $pTitel);
    $teilnehmer->setValue2Var('name', $pName);
    $teilnehmer->setValue2Var('vorname', $pVorname);
    $teilnehmer->setValue2Var('email', $pEmail);
    $teilnehmer->setValue2Var('email_anzeige', $pEmail);
    $teilnehmer->setValue2Var('schul_nr', $pSchulNr);

    return $teilnehmer;
  }

  private function getTeilnehmerFromDb($teilnehmerToSearch)
  {
    $dbwTeilnehmer = new \DBWorkTeilnehmer(1, true);
    $dbwTeilnehmer->newSearch();
    $dbwTeilnehmer->fromobject->name = $teilnehmerToSearch->getVarValue('name');
    $dbwTeilnehmer->fromobject->vorname = $teilnehmerToSearch->getVarValue('vorname');
    $teilnehmer = $dbwTeilnehmer->getTeilnehmer();

    $dbwKommunikation = new \DBWorkKommunikation('T', 1, true);
    $dbwKommunikation->allkom = true;
    $dbwUser = new \DBWorkUser(1, true);
    foreach ($teilnehmer as $tn) {
      
      if (\StringOperations::strtolower(trim($tn->getVarValue('name'))) == \StringOperations::strtolower(trim($teilnehmerToSearch->getVarValue('name')))
         && \StringOperations::strtolower(trim($tn->getVarValue('vorname'))) == \StringOperations::strtolower(trim($teilnehmerToSearch->getVarValue('vorname')))) {
        $kommunikationen = $dbwKommunikation->getKommunikationByNrTypArt($tn->getVarValue('id'), 'T', 'E');
        foreach ($kommunikationen as $kommunikation) {
          if (\StringOperations::strtolower(trim($kommunikation->wert)) == \StringOperations::strtolower(trim($tn->getVarValue('email_anzeige')))) {
            $logins = $dbwUser->getUsersByTnr($tn->id);
            if (count($logins) == 0) {
              return $tn;
            }
          }
        }
      }
    }

    return null;
  }

  private function getUndoableInsertTeilnehmer($teilnehmer)
  {
    $dbwTeilnehmer = new \DBWorkTeilnehmer(1, true);
    $dbwKommunikation = new \DBWorkKommunikation('T', 1, true);

    $doFunction = function() use ($teilnehmer, &$tnr, $dbwTeilnehmer) {
      $teilnehmer->id = $dbwTeilnehmer->insertTeilnehmer($teilnehmer, false, true);
      
      $tnr = $teilnehmer->id;

      return $dbwTeilnehmer->getTeilnehm($teilnehmer->id, true);
    };

    $undoFunction = function() use (&$tnr, $dbwTeilnehmer, $dbwKommunikation) {
      $dbwTeilnehmer->deleteTeilnehmer($tnr);
      $kommunikationen = $dbwKommunikation->getKommunikationsblock($tnr);
      foreach ($kommunikationen as $kommunikation) {
        $dbwKommunikation->deleteKommunikation($kommunikation);
      }
      $tnr = 0;
    };

    return new \UndoAble($doFunction, $undoFunction);
  }

  private function getUndoableInsertWebUser($webUser)
  {
    $dbwWebUser = new \DBWorkUser(1, true);


    $doFunction = function() use ($webUser, &$wuId, $dbwWebUser) {
      $webUser->id = $dbwWebUser->insertUser($webUser, true);
      
      $wuId = $webUser->id;

      return $webUser;
    };

    $undoFunction = function() use (&$wuId, $dbwWebUser) {
      $dbwWebUser->deleteWebUser($wuId);
      $wuId = 0;
    };

    return new \UndoAble($doFunction, $undoFunction);
  }

  private function insertWebUser($login, $tnr)
  {
    $webUser = new \Benutzer();
    $webUser->dnr = -1;
    $webUser->login = $login;
    $webUser->admin = -1;
    $webUser->tnr = $tnr;
    $webUser->anr = -1;
    $webUser->ben = -1;

    $undoableInsertWebUser = $this->getUndoableInsertWebUser($webUser);
    $webUser = $undoableInsertWebUser->doOnce();
    $this->undoByError[] = $undoableInsertWebUser;

    return $webUser;
  }

  private function insertWebToolsUsers($userId)
  {
    $dbwWebToolsStdTempl = new \DBWorkWebToolsStdTempl(1, true);
    $dbwWebToolsUsers = new \DBWorkWebToolsUsers(1, true);
    $webToolsStdTempl = $dbwWebToolsStdTempl->get4Teilnehmer();
    $wtus = array();
    foreach ($webToolsStdTempl as $wtst) {
      $wtu = $this->getWebToolsUsers4Template($wtst, $userId);
      $wtu->id = $dbwWebToolsUsers->insertWebToolsUsers($wtu, true);
      $wtus[] = $wtu;
    }
    
    return $wtus;
  }

  private function getWebToolsUsers4Template($webToolsStdTempl, $userId)
  {
    $webToolsUsers = new \WebToolsUsers();
    $webToolsUsers->template_id = $webToolsStdTempl->template_id;
    $webToolsUsers->tool_id = $webToolsStdTempl->tool_id;
    $webToolsUsers->user_id = $userId;
    $webToolsUsers->validfrom = $webToolsStdTempl->validfrom;
    $webToolsUsers->validuntil = $webToolsStdTempl->validuntil;

    if (\DateTimeOperations::isDateTimeEmptyOrDefault($webToolsUsers->validfrom)) {
      $webToolsUsers->validfrom = \DateTimeOperations::getDateNow();
    }

    if (\DateTimeOperations::isDateTimeEmptyOrDefault($webToolsUsers->validuntil)) {
      $webToolsUsers->validuntil = '31.12.2099';
    }

    return $webToolsUsers;
  }

  private function insertPasswort($webUser, $pPasswortHash, $pHashversion, $auth_extern)
  {
    $dbwUser = new \DBWorkUser(1, true);
    $dbwUser->setHashedPassWD($webUser->login, $pPasswortHash, $pHashversion, $auth_extern);
  }

  private function rewindNeusLogin()
  {
    foreach ($this->undoByError as $undoable) {
      $undoable->undo();
    }
  }
}