<?php
/**
 * @copyright (c) Kufer Software GmbH, Oderstraße 7, D-84453 Mühldorf
 */

namespace Kufer\Web\KuferTools\Utils;

use Kufer\Web\KuferTools\Basis\UseCaseBuilder\SpecificToolSection;
use Kufer\Web\KuferTools\Basis\UseCaseBuilder\ToolSection;
use Kufer\Web\KuferTools\Utils\WssField\IWssField;
use Kufer\Web\KuferTools\Utils\WssField\WssFactory;

class WssHandler
{
  private $user;
  private $toolId;
  private $toolSectionId;

  
  private $changedInfos = array();

  
  private $columns = array();

  public function __construct(int $toolId, int $toolSectionId, $user)
  {
    $this->user = $user;
    $this->toolId = $toolId;
    $this->toolSectionId = $toolSectionId;
  }

  public function getColumnValuesFromPost(string $requestPrefix = '', string $cachePrefix = '', bool $recache = false)
  {
    $result = array();
    $columns = $this->getColumnsCached($cachePrefix, $recache);
    $wssFactory = new WssFactory();

    foreach ($columns as $column) {
      
      
      $wssField = $wssFactory->getWss($this->toToolSection(), new \ToolSettings(), $column);

      $wssFieldInPost = $wssField->inPost($requestPrefix);
      if ($wssFieldInPost) {
        $datamodul = $wssField->getDatamodulName();
        if (!isset($result[$datamodul])) {
          $result[$datamodul] = array();
        }
        $result[$datamodul][$wssField->getFieldName()] = $wssField->getValueFromPost($requestPrefix);
      }
    }

    return $result;
  }

  public function checkColumnValues(\ToolSettings $toolSettings, $columnValues, $checkPflichtfelder = true, string $cachePrefix = '', bool $recache = false)
  {
    $wrongFields = array();

    $wssFactory = new WssFactory();

    
    
    

    $columns = $this->getColumnsCached($cachePrefix, $recache);
    foreach ($columns as $column) {
      $wssField = $wssFactory->getWss($this->toToolSection(), $toolSettings, $column);

      $datamodul = $wssField->getDatamodulName();
      $fieldname = $wssField->getFieldName();

      $value = '';
      if (isset($columnValues[$datamodul], $columnValues[$datamodul][$fieldname])) {
        $value = $columnValues[$datamodul][$fieldname];
      }

      if (!$wssField->isValid($value, $checkPflichtfelder)) {
        $wrongFields[] = $wssField;
      }
    }

    return $wrongFields;
  }

  public function getChangedFieldnames(
    \ToolSettings $toolSettings,
    $origDm,
    $columnValues,
    string $cachePrefix = '',
    bool $recache = false
  ) {
    $infos = $this->getChangedInfoCached($toolSettings, $origDm, $columnValues, $cachePrefix, $recache);

    return $infos['changedFields'];
  }

  public function getChangedDm(
    \ToolSettings $toolSettings,
    $origDm,
    $columnValues,
    string $cachePrefix = '',
    bool $recache = false
  ) {
    $infos = $this->getChangedInfoCached($toolSettings, $origDm, $columnValues, $cachePrefix, $recache);

    return $infos['changed'];
  }

  private function getChangedInfoCached(
    \ToolSettings $toolSettings,
    $origDm,
    $columnValues,
    string $cachePrefix = '',
    bool $recache = false
  ) {
    
    if ($recache || !array_key_exists($cachePrefix, $this->changedInfos)) {
      $this->changedInfos[$cachePrefix] = $this->getChangedInfo(
        $toolSettings,
        $origDm,
        $columnValues,
        $cachePrefix,
        $recache
      );
    }

    return $this->changedInfos[$cachePrefix];
  }

  private function getChangedInfo(\ToolSettings $toolSettings, $origDm, $columnValues, string $cachePrefix = '', bool $recache = false)
  {
    $columns = $this->getColumnsCached($cachePrefix, $recache);
    $changedDm = clone($origDm);

    $changedFields = array();

    $wssFactory = new WssFactory();

    $wssFieldsWithIndices = array();
    $i = 0;
    foreach ($columns as $column) {
      $wssFieldsWithIndices[] = array($i, $wssFactory->getWss($this->toToolSection(), $toolSettings, $column));
      $i += 1;
    }

    
    
    usort($wssFieldsWithIndices, static function(array $lhs, array $rhs): int {
      list($lhsIdx, $lhs) = $lhs;
      list($rhsIdx, $rhs) = $rhs;
      foreach ($lhs->getDependencies() as $dependency) {
        list($datamodul, $field) = $dependency;
        if ($datamodul === $rhs->getDatamodulName() && $field === $rhs->getFieldName()) {
          return 1;
        }
      }

      foreach ($rhs->getDependencies() as $dependency) {
        list($datamodul, $field) = $dependency;
        if ($datamodul === $lhs->getDatamodulName() && $field === $lhs->getFieldName()) {
          return -1;
        }
      }

      return $lhsIdx < $rhsIdx;
    });

    
    $wssFields = array_map(static function(array $ary) {
      return $ary[1];
    }, $wssFieldsWithIndices);
    unset($wssFieldsWithIndices);

    foreach ($wssFields as $wssField) {
      $changedInfo = $wssField->getChangedInfo($columnValues, $changedDm, $changedFields);
      $changedDm = $changedInfo['changed'];
      $changedFields = $changedInfo['changedFields'];
    }

    return array('changed' => $changedDm, 'changedFields' => $changedFields);
  }

  
  public function getColumnsCached(string $cachePrefix = '', bool $recache = false)
  {
    if ($recache || !array_key_exists($cachePrefix, $this->columns)) {
      $this->columns[$cachePrefix] = $this->getColumns();
    }

    return $this->columns[$cachePrefix];
  }

  private function toToolSection(): ToolSection
  {
    return new SpecificToolSection($this->toolId, $this->toolSectionId);
  }

  private function getColumns()
  {
    if (!is_null($this->user) && !$this->user->isEmpty()) {
      $wssInFiles = new WssInFiles();

      return $wssInFiles->getWss($this->toToolSection(), new \ToolSettings(), $this->toolSectionId, $this->user);
    } else {
      return array();
    }
  }

  
  public static function getErrorMessage($pWrongFields)
  {
    $result = '';
    if (count($pWrongFields) > 0) {
      $result .= 'Das Formular wurde nicht korrekt ausgefüllt. Bitte überprüfen Sie folgende Felder:';
      $result .= '<ul>';
      foreach ($pWrongFields as $wssField) {
        $column = $wssField->getDmColumnMitDefaultBeruecksichtigt();
        $result .= '<li>' . $column->title . '</li>';
      }
      $result .= '</ul>';
    }

    return $result;
  }

  
  public function getFieldsInReadableFormat($pFields, string $cachePrefix = '', bool $recache = false)
  {
    $columns = $this->getColumnsCached($cachePrefix, $recache);
    $columnsWithKeys = \ArrayOperations::setAttributAsKey($columns, 'fieldname');
    $result = array();

    foreach ($pFields as $field) {
      if (isset($columnsWithKeys[$field])) {
        $result[$field] = $columnsWithKeys[$field]->title;
      }
    }

    return $result;
  }

  
  public static function getFieldsInReadableFormatNoColumns($pFields)
  {
    $mapping = array('datum' => 'Datum', 'ue' => 'UE', 'zeit_beg' => 'Beginn', 'minuten' => 'Minuten', 'pause' => 'Pause',
        'zeit_ende' => 'Ende', 'ausfall' => 'Status', 'ort' => 'Kursort', 'bemerkungen' => 'Bemerkung');
    $result = array();

    foreach ($pFields as $field) {
      if (isset($mapping[$field])) {
        $result[$field] = $mapping[$field];
      } else {
        $result[$field] = $field;
      }
    }

    return $result;
  }
}