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

declare(strict_types = 1);

namespace Kufer\Web\Classes\Dbfilter;


class BelegungenSQLFilter extends BasicSQLFilter
{
  public const FILTER_OPTION_FIRMA_ID = 'firmaid';
  public const FILTER_OPTION_TEILNEHMER = 'teilnehmer';
  public const FILTER_OPTION_KURSE = 'kurse';

  protected function __construct()
  {
    parent::__construct();

    $this->registerDb('Id', 'id', static::TYPE_INTEGER);
    $this->registerDb('TeilnehmerId', 'tnr', static::TYPE_IDENTIFIER_NO_GUID);
    $this->registerDb('FirmaId', 'firma', static::TYPE_IDENTIFIER_NO_GUID);
    $this->registerDb('FirmaBelegungId', 'firmabelegid', static::TYPE_INTEGER);
    $this->registerDb('Anmeldedatum', 'anm_datum', static::TYPE_DATETIME);
    $this->registerDb('Bearbeiter', 'bearbeiter', static::TYPE_STRING);
    $this->registerDb('Status', 'status_1', static::TYPE_STRING);
    $this->registerDb('Eintritt', 'eintritt', static::TYPE_DATE);
    $this->registerDb('Austritt', 'austritt', static::TYPE_DATE);
    $this->registerDb('Bezug', 'bezug', static::TYPE_INTEGER);
    $this->registerDb('Kursnummer', 'knr', static::TYPE_STRING);
  }

  public function getTablePraeffix(): string
  {
    return 'b';
  }

  public function equalsId($id): IFilter
  {
    $this->applyFilterCurrent(
      static::FILTER_OPTION_ID,
      SQLFilterUtils::filterEqualsIdInt('id', $id)
    );

    return $this;
  }

  public function inId(iterable $ids): IFilter
  {
    $this->applyFilterCurrent(
      static::FILTER_OPTION_ID,
      SQLFilterUtils::filterInIdInt('id', $ids)
    );

    return $this;
  }

  
  public function isFirmenanmeldung(): IFilter
  {
    $this->notAny(function() {
      
      $this->equalsFirma(0);
    });

    return $this;
  }

  
  public function equalsStatus($status): IFilter
  {
    $this->inStatus(array($status));

    return $this;
  }

  
  public function inStatus($status): IFilter
  {
    if (\is_string($status)) { 
      $status = \StringOperations::str_split($status);
    }

    $status = (new \Kufer\Web\Classes\Stream\ArrayStream($status))
      ->filter(\FunctionOperations::not(\FunctionOperations::args(\FunctionOperations::equalsStrict(), '-')))
      ->map(static function($char) {
        if ($char === 'A') {
          return array('A', '', ' ');
        } else {
          return array($char);
        }
      })
      ->reduce('\\array_merge', array());

    $this->applyRegisteredCall($this->getRegisteredCallByName('Status'), 'in', array($status), false, null);

    return $this;
  }

  
  public function applyBelegungenFirmaBelegungIdFilter(BelegungenSQLFilter $filter): IFilter
  {
    $filter->makeImmutable();

    if ($filter->isEmpty()) {
      return $this;
    }

    $this->applyFilterCurrent(
      static::FILTER_OPTION_FIRMA_ID,
      function(\SelectQueryBuilder $builder) use ($filter): \SelectQueryBuilder {
        $firmenIdSql = $filter->createSql($builder->getDBOperation());
        if (trim($firmenIdSql) === '') {
          return $builder;
        }

        $firmenBelegungenBuilder = ((\DBWorkBelegung::getDefaultInstance($builder->getDBOperation()->dbnr)))->findByFilterQuery($filter)
          ->select(':table:.tnr');

        $var = $builder->uniqueVar();

        return $builder->and(":table:.firma IN (:$var:)")
          ->paramSelectQuery($var, $firmenBelegungenBuilder);
      }
    );

    return $this;
  }

  
  public function applyTeilnehmerFilter(\Kufer\Web\Classes\Dbfilter\TeilnehmerSQLFilter $filter): IFilter
  {
    $filter->makeImmutable();

    if ($filter->isEmpty()) {
      return $this;
    }

    $this->applyFilterCurrent(
      static::FILTER_OPTION_TEILNEHMER,
      function(\SelectQueryBuilder $builder) use ($filter): \SelectQueryBuilder {
        $tnBuilderSql = $filter->createSql($builder->getDBOperation());
        if (\trim($tnBuilderSql) === '') {
          return $builder;
        }

        $tnBuilder = ((\DBWorkTeilnehmer::getDefaultInstance($builder->getDBOperation()->dbnr)))->findByFilterQuery($filter)
          ->select('t.nr');

        $var = $builder->uniqueVar();

        return $builder->and(":table:.tnr IN (:$var:)")
          ->paramSelectQuery($var, $tnBuilder);
      }
    );

    return $this;
  }

  public function applyKurseFilter(\Kufer\Web\Classes\Dbfilter\KurseSQLFilter $filter): IFilter
  {
    $filter->makeImmutable();

    if ($filter->isEmpty()) {
      return $this;
    }

    $this->applyFilterCurrent(
      static::FILTER_OPTION_KURSE,
      function(\SelectQueryBuilder $builder) use ($filter): \SelectQueryBuilder {
        $kurseBuilderSql = $filter->createSql($builder->getDBOperation());
        if (\trim($kurseBuilderSql) === '') {
          return $builder;
        }

        $kurseBuilder = ((\DBWorkKurse::getDefaultInstance($builder->getDBOperation()->dbnr)))->findByFilterQuery($filter)
          ->select(':table:.nr');

        $var = $builder->uniqueVar();

        return $builder->and(":table:.knr IN (:$var:)")
          ->paramSelectQuery($var, $kurseBuilder);
      }
    );

    return $this;
  }

  
  public function isKinderBelegungen(bool $pAlleBelegungenKinderkurs = true): self
  {
    if (\System::isKuferSql5()) {
      return $this->all(static function(BelegungenSQLFilter $filter) use ($pAlleBelegungenKinderkurs): BelegungenSQLFilter {
        $filter->equalsBezug(3);

        $filter->notAny(static function(BelegungenSQLFilter $filter): void {
          $filter->equalsFirmaId(0);
        });

        if ($pAlleBelegungenKinderkurs) {
          $filter->notAny(static function(BelegungenSQLFilter $filter) : BelegungenSQLFilter {
            $kurseFilter = \Kufer\Web\Classes\Dbfilter\KurseSQLFilter::create();
            $kurseFilter->equalsTyp('K');
            $filter->applyKurseFilter($kurseFilter);

            return $filter;
          });
        }

        return $filter;
      });
    } else {
      $this->applyFalse(); 

      return $this;
    }
  }
}