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


class KommunikationsAPI
{
  
  public static $_changedKommFields = array('id', 'nr', 'typ', 'art', 'bezeichner', 'wert', 'sort');

  
  public static function correctKommunikation($pKommTupleAry, $pCorrectMode = 'insert', $noMapping = false)
  {
    $abgleichAPI = new AbgleichAPI();
    if (!$abgleichAPI->isAktiviert()) {
      return 'nichtAktiviert';
    }

    $message = new XMLNode('kommunikationsdaten');
    
    
    $dbworkWebReplikatSettings = new DBWorkWebReplikatSettings();
    $webreplikatsetting = $dbworkWebReplikatSettings->getMaxPk('kommunikation');
    $childNode = new XMLNode('highestpk', '-', 'leer="true"');
    if (isset($webreplikatsetting) && $webreplikatsetting->value != '') {
      $childNode = new XMLNode('highestpk', $webreplikatsetting->value);
    }
    $message->addChild($childNode);

    $nothingToDo = true;
    foreach ($pKommTupleAry as $kommunikationsTuple) {
      $kommunikation = $kommunikationsTuple->getFirst();
      $fields = $kommunikationsTuple->getSecond();
      $kommOriginal = $kommunikationsTuple->getThird();

      if ($pCorrectMode == 'update') {
        $oldobjectNode = new XMLNode('oldobject');
      }

      $kommNode = new XMLNode('kommunikation');
      
      $kommId = $kommunikation->id;
      
      $kommNode->addChild(new XMLNode('id', $kommId));

      $nothingToDo = self::addFieldsToKommunikationNode($kommNode, $kommunikation, $fields);
      if ($pCorrectMode == 'update') {
        $nothingToDo = self::addFieldsToKommunikationNode($oldobjectNode, $kommOriginal, $fields) && $nothingToDo;
        $kommNode->addChild($oldobjectNode);
      }

      $message->addChild($kommNode);
    } 

    if (!$nothingToDo) {
      
      if ($pCorrectMode == 'update') { 
        $operation = AbgleichAPI::ABGLEICH_KOMMKORREKTUR;
      } 
      
      elseif ($pCorrectMode == 'insert') {
        $operation = AbgleichAPI::ABGLEICH_KOMMUNIKATION;
      } 
      else { 
        $operation = AbgleichAPI::ABGLEICH_KOMMDELETE;
      } 

      $abgleichAPI = new AbgleichAPI();
      
      $abgleichAPI->sendeNachricht(
        $operation,
        new Nutzlast($message),
        null,
        $noMapping
      );
      
      
      return 'sendDone';
    } 
    
    return 'noCorrection';
  }

  

  public static function cleanKommunikationOfTeilnehmer($teilnehmer)
  {
    $alleVars = get_object_vars($teilnehmer);
    foreach ($alleVars as $key => $var) {
      if ($var instanceof Kommunikation) {
        if ($var->wert == '') {
          $teilnehmer->{$key} = null;
        }
      }
    }

    return $teilnehmer;
  }

  public static function deleteKommunikation($pKommunikationen)
  {
    $abgleichAPI = new AbgleichAPI();
    if (!$abgleichAPI->isAktiviert()) {
      return 'nichtAktiviert';
    }
    $kommunikationen = $pKommunikationen;
    if (!is_array($pKommunikationen)) {
      if ($pKommunikationen instanceof Kommunikation) {
        $kommunikationen = array($pKommunikationen);
      } else {
        throw new InvalidArgumentException('$pKommunikationen ist weder ein Kommunikationsarray noch ein Kommunikationsobjekt');
      }
    }

    $message = new XMLNode('kommunikationsdaten');
    
    
    $dbworkWebReplikatSettings = new DBWorkWebReplikatSettings();
    $webreplikatsetting = $dbworkWebReplikatSettings->getMaxPk('kommunikation');
    $childNode = new XMLNode('highestpk', '-', 'leer="true"');
    if (isset($webreplikatsetting) && $webreplikatsetting->value != '') {
      $childNode = new XMLNode('highestpk', $webreplikatsetting->value);
    }
    $message->addChild($childNode);

    foreach ($kommunikationen as $kommunikation) {
      $kommNode = new XMLNode('kommunikation');
      
      $kommId = $kommunikation->id;
      
      $kommNode->addChild(new XMLNode('id', $kommId));

      $message->addChild($kommNode);
    } 

    $abgleichAPI = new AbgleichAPI();
    
    $abgleichAPI->sendeNachricht(
      AbgleichAPI::ABGLEICH_KOMMDELETE,
      new Nutzlast($message)
    );

    return 'sendDone';
  }

  
  private static function addFieldsToKommunikationNode($pKommNode, $pKommunikation, $fields)
  {
    $dbwKomm = new DBWorkKommunikation();
    $nothingToDo = true;
    
    foreach ($fields as $fieldName) {
      if ($dbwKomm->canupdate($fieldName)) {
        $fieldValue = $pKommunikation->getDMZValue($fieldName);
        $fieldAttr = '';
        if ($fieldValue === '') {
          $fieldValue = '-';
          $fieldAttr = 'leer="true"';
        }
        $fieldName = $dbwKomm->translateVarName($fieldName);
        $childNode = new XMLNode($fieldName, $fieldValue, $fieldAttr);
        $pKommNode->addChild($childNode);
        $nothingToDo = false;
      } 
    }  

    return $nothingToDo;
  }

  

  
  public static function getOrigKommunikation($pPerson)
  {
    
    $dbwKomm = new DBWorkKommunikation();
    $persObjVars = get_object_vars($pPerson);
    
    
    
    $origKommAry = array();
    foreach ($persObjVars as $persObjVar) {
      
      
      if ($persObjVar instanceof Kommunikation && !$persObjVar->isEmpty() && $persObjVar->id != null) {
        $origKommunikation = $dbwKomm->getKommunikation($persObjVar->id);
        $origKommAry[] = $origKommunikation;
      }
    } 

    return $origKommAry;
  }

  

  
  public static function getCurrentKommunikation($pPerson, $pOnlyWithId = true)
  {
    $persObjVars = get_object_vars($pPerson);
    
    
    
    $aktuellKommAry = array();
    foreach ($persObjVars as $persObjVar) {
      
      
      if ($persObjVar instanceof Kommunikation && !$persObjVar->isEmpty()) {
        if ($pOnlyWithId) {
          if ($persObjVar->id != null) {
            $aktuellKommAry[] = $persObjVar;
          }
        } else {
          $aktuellKommAry[] = $persObjVar;
        }
      }
    } 

    return $aktuellKommAry;
  }

  

  
  public static function getKommEntry($pKommObjAry, $pId)
  {
    $kommObj = null;
    if (is_array($pKommObjAry)) {
      $cnt = count($pKommObjAry);
      for ($i = 0; $i < $cnt; $i++) {
        if ($pId == $pKommObjAry[$i]->id) {
          $kommObj = $pKommObjAry[$i];
          break;
        }
      } 
    }

    return $kommObj;
  }

  

  
  public static function buildAndSendKommunikation($pPerson, $pOrigKommAry, $pLoeschen = false, $pVorhandeneIdPruefen = true, $pSortiertesKommAry = array())
  {
    $kommTupleAry4Update = array();
    $kommTupleAry4Insert = array();
    $kommTupleAry4Delete = array();
    $kommArray = self::selectKommArray($pPerson, $pSortiertesKommAry);

    
    
    
    $highestSort = 0;
    foreach ($kommArray as $persObjVar) {
      
      
      if (!empty($persObjVar->sort) && $persObjVar->sort > $highestSort) {
        $highestSort = $persObjVar->sort;
      }
      
      
      $origKommunikation = null;
      if ($persObjVar->id != '') {
        $origKommunikation = self::getKommEntry($pOrigKommAry, $persObjVar->id);
      }
      
      if ($origKommunikation != null) {
        
        if ($persObjVar->wert != $origKommunikation->wert || $pLoeschen == true) {
          $kommTupleAryUpd = new Tuple($persObjVar, self::$_changedKommFields, $origKommunikation);
          if (trim($persObjVar->wert) == '') {
            $kommTupleAry4Delete[] = $kommTupleAryUpd;
          } else {
            $kommTupleAry4Update[] = $kommTupleAryUpd;
          }
        }
      }
      
      
      
      else {
        if ($persObjVar->id != '' || !$pVorhandeneIdPruefen) {
          $kommTupleAry4Ins = new Tuple($persObjVar, self::$_changedKommFields, null);
          $kommTupleAry4Insert[] = $kommTupleAry4Ins;
        }
      } 
    } 

    foreach ($kommTupleAry4Insert as $kommTuple) {
      $kommEintrag = $kommTuple->getFirst();
      if (empty($kommEintrag->sort)) {
        $kommEintrag->sort = $highestSort + 1;
        $kommTuple->setFirst($kommEintrag);
        $highestSort++;
      }
    }

    self::correctKommunikation($kommTupleAry4Insert, 'insert');
    self::correctKommunikation($kommTupleAry4Update, 'update');
    self::correctKommunikation($kommTupleAry4Delete, 'delete');
  }

  

  private static function selectKommArray($pPerson, $pSortiertesKommAry)
  {
    $kommArray = array();
    if (!empty($pSortiertesKommAry)) {
      $kommArray = $pSortiertesKommAry;
    } else {
      $persObjVars = get_object_vars($pPerson);
      foreach ($persObjVars as $persObjVar) {
        if ($persObjVar instanceof Kommunikation && !$persObjVar->isEmpty()) {
          $kommArray[] = $persObjVar;
        }
      }
    }

    return $kommArray;
  }

  public static function sortiereKommunikation($unsortiertesKommArray)
  {
    $sortiertesKommArray = array();
    $dbwhlk = new DBWorkHLKommunikation();
    $kommreihenfolgeObjektArray = $dbwhlk->getAll();
    $kommreihenfolgeStatusArray = array_map(function($el) {return $el->art;}, $kommreihenfolgeObjektArray);
    
    foreach ($kommreihenfolgeStatusArray as $status) {
      foreach ($unsortiertesKommArray as $key => $komm) {
        if ($komm->art == $status) {
          $sortiertesKommArray[] = $komm;
          unset($unsortiertesKommArray[$key]);
          break;
        }
      }
    }
    
    $sortiertesKommArray = array_merge($sortiertesKommArray, $unsortiertesKommArray);

    for ($i = 0; $i < count($sortiertesKommArray); $i++) {
      $sortiertesKommArray[$i]->sort = $i + 1;
    }

    return $sortiertesKommArray;
  }

  
  public static function revertChangesOfKommunikation4DMZ($pDbwPerson, $pOrigPerson, $pCurrentKommAry, $pOrigKommAry, $pNoProtocol)
  {
    $dbwKommunikation = new DBWorkKommunikation($pOrigPerson->getDbTyp());

    
    
    foreach ($pCurrentKommAry as $actualKomm) {
      $identicalIdsFound = false;
      foreach ($pOrigKommAry as $origKomm) {
        if ($origKomm->id == $actualKomm->id) {
          $identicalIdsFound = true;
          break;
        }
      }
      
      if (!$identicalIdsFound) {
        $origKomm = clone $actualKomm;
        $origKomm->wert = '';
      }
      $dbwKommunikation->updateKommunikation($origKomm, $actualKomm, $pNoProtocol);
    }

    
    if ($pOrigPerson->getDbTyp() == 'T') {
      
      
      $pDbwPerson->updateTeilnehmer($pOrigPerson, $pNoProtocol);
    } elseif ($pOrigPerson->getDbTyp() == 'D') {
      $pDbwPerson->updateDozent($pOrigPerson, $pNoProtocol);
    } elseif ($pOrigPerson->getDbTyp() == 'A') {
      $pDbwPerson->updateAdresse($pOrigPerson, $pNoProtocol);
    }
  }

  
  public static function getKommunikationInfosPerDMZ($pTnId)
  {
    $abgleichAPI = new AbgleichAPI();
    $message = new XMLNode('teilnehmer');
    $message->addChild(new XMLNode('id', $pTnId, '', '', true));
    $result = $abgleichAPI->sendeNachricht(
      AbgleichAPI::ABGLEICH_GET_KOMMUNIKATION_TEILNEHMER,
      new Nutzlast($message)
    );

    return JsonOperations::decode($result->reason);
  }

  
  public static function sortKommunikationen($pKommunikationen)
  {
    $kommunikationen = $pKommunikationen;
    usort($kommunikationen, function($komm1, $komm2) {
      if ($komm1->Sort == $komm2->Sort) {
        return 0;
      } elseif ($komm1->Sort < $komm2->Sort) {
        return -1;
      } else {
        return 1;
      }
    });

    return $kommunikationen;
  }

  
  public static function gruppiereKommunikationenNachArt($pKommunikationen)
  {
    $kommunikationen = $pKommunikationen;

    return array_reduce($kommunikationen, function($result, $kommunikation) {
      if (!isset($result[$kommunikation->Art])) {
        $result[$kommunikation->Art] = array();
      }
      $result[$kommunikation->Art][] = $kommunikation;

      return $result;
    }, array());
  }

  
  public static function addKommunikation(\Kommunikation $komm, bool $noMapping = false): string
  {
    
    $komm->sort = null;

    $kommTuple = new Tuple($komm, KommunikationsAPI::$_changedKommFields, null);

    return KommunikationsAPI::correctKommunikation(array($kommTuple), 'insert', $noMapping);
  }
}