<?php

namespace domain\_;

abstract class AbstractRepository extends AbstractService implements RepositoryInterface
{
    const WITH = 'with';
    const JOIN_WITH = 'join_with';
    const ORDER_BY = 'orderby';
    const ATTRIBUTE_ID_PRODUCER = 'attribute_id_producer';

    public function loadQuery(string $serviceClass)
    {
        $this->query = $this->loadService($serviceClass);
    }

    public function createQuery()
    {
        $this->query->createQuery();

        $this->defaultWith();
        $this->defaultJoinWith();

        return $this->query;
    }

    public function createDefaultQuery(bool $filterStatus = true): RepositoryQueryInterface
    {
        $this->createQuery();
        if($filterStatus) {
            $this->defaultStatus();
        }
        $this->defaultWith();
        $this->defaultJoinWith();
        $this->defaultFilterProducerContext();
        $this->defaultOrderBy();

        return $this->query;
    }

    public function defaultStatus(): void
    {
        $class = new \ReflectionClass($this->query->getDefinition()->getEntityFqcn());
        if($class->implementsInterface('domain\_\StatusInterface')) {
            $this->query->filterIsStatusOnlineAndOffline();
        }
    }

    public function defaultWith(): void
    {
        $defaultOptions = $this->getDefaultOptionsSearch();
        if (is_array($defaultOptions['with']) && count($defaultOptions['with'])) {
            $this->query->with($defaultOptions['with']);
        }
    }

    public function defaultJoinWith(): void
    {
        $defaultOptions = $this->getDefaultOptionsSearch();
        if (is_array($defaultOptions['join_with']) && count($defaultOptions['join_with'])) {
            $this->query->joinWith($defaultOptions['join_with']);
        }
    }

    public function defaultFilterProducerContext(): void
    {
        $defaultOptions = $this->getDefaultOptionsSearch();
        if(isset($defaultOptions['attribute_id_producer'])
            && $defaultOptions['attribute_id_producer']
            && $this->getProducerContext()) {
            $this->query->andWhere([$defaultOptions['attribute_id_producer'] => $this->getProducerContextId()]);
        }
    }

    public function defaultOrderBy(): void
    {
        $defaultOptions = $this->getDefaultOptionsSearch();
        if(isset($defaultOptions['orderby']) && $defaultOptions['orderby']) {
            $this->query->orderBy($defaultOptions['orderby']);
        }
    }

    public function findAll()
    {
        return $this->createQuery()->find();
    }

    public function queryAll()
    {
        return $this->createQuery();
    }

    public function queryDefaultAll()
    {
        return $this->createDefaultQuery();
    }
}