<?php
/**
 * @author Colinet Julien
 */

namespace CpCreation\VitiCore\Repository;

use CpCreation\VitiCore\Behavior\HasDisable;
use CpCreation\VitiCore\Behavior\HasSortable;
use CpCreation\VitiCore\Behavior\IsSoftDeletable;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectRepository;

abstract class BaseRepository extends ServiceEntityRepository implements ObjectRepository
{
    private $entity;

    /**
     * BaseRepository constructor.
     * @param ManagerRegistry $registry
     * @param string          $entityClass
     * @throws \ReflectionException
     */
    public function __construct(ManagerRegistry $registry, string $entityClass)
    {
        parent::__construct($registry, $entityClass);
        $this->entity = new \ReflectionClass($entityClass);
    }

    public function persist($object)
    {
        $this->_em->persist($object);
    }

    public function flush()
    {
        $this->_em->flush();
    }

    public function save($object)
    {
        $this->_em->persist($object);
        $this->_em->flush();
    }

    public function delete($object)
    {
        $this->_em->remove($object);
        $this->_em->flush();
    }

    public function softDelete($object)
    {
        $this->_em->remove($object);
    }

    public function disable($object)
    {
        if ($object instanceof HasDisable) {
            $object->setDisabled(true);
            $this->save($object);

            return $object;
        }

        return false;
    }

    public function enable($object)
    {
        if ($object instanceof HasDisable) {
            $object->setDisabled(false);
            $this->save($object);

            return $object;
        }

        return false;
    }

    public function moveUp($object)
    {
        if ($object instanceof HasSortable) {
            if ($object->getPosition() > 0) {
                $object->setPosition($object->getPosition() - 1);
                $this->save($object);

                return $object;
            }

            return false;
        }

        return false;
    }

    public function moveDown($object)
    {
        if ($object instanceof HasSortable) {
            if ($object->getPosition() > 0) {
                $object->setPosition($object->getPosition() + 1);
                $this->save($object);

                return $object;
            }

            return false;
        }

        return false;
    }

    public function findByCreatedAdminAt($sort)
    {
        $qb    = $this->createQueryBuilder('r')
                      ->orderBy('r.createdAt', $sort);
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findByCreatedAt($sort)
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.createdAt', $sort);
        if (in_array(HasDisable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.disabled = FALSE');
        }
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findByPositionOrderAdmin()
    {
        $qb    = $this->createQueryBuilder('r')
                      ->orderBy('r.position', 'ASC');
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }

        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findByPositionOrder()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.position', 'ASC');
        if (in_array(HasDisable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.disabled = FALSE');
        }
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findByPositionOrderQuery()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.position', 'ASC');
        if (in_array(HasDisable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.disabled = FALSE');
        }
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }

        return $qb;
    }

    public function findByTitleOrderAdmin()
    {
        $qb    = $this->createQueryBuilder('r')
                      ->orderBy('r.title', 'ASC');
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findByTitleOrderAdminQuery()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.title', 'ASC');
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        if (in_array(HasDisable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.disabled = FALSE');
        }
        return $qb;
    }

    public function findByTitleOrder()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.title', 'ASC');
        if (in_array(HasDisable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.disabled = FALSE');
        }
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findByTitleOrderQuery()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.title', 'ASC');
        if (in_array(HasDisable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.disabled = FALSE');
        }
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        return $qb;
    }

    public function findByNameOrderAdmin()
    {
        $qb    = $this->createQueryBuilder('r')
                      ->orderBy('r.name', 'ASC');
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findByNameOrderAdminQuery()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.name', 'ASC');
        if (in_array(HasDisable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.disabled = FALSE');
        }
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        return $qb;
    }

    public function findByNameOrder()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.name', 'ASC');
        if (in_array(HasDisable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.disabled = FALSE');
        }
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        $query = $qb->getQuery();

        return $query->execute();
    }

    public function findByNameOrderQuery()
    {
        $qb = $this->createQueryBuilder('r')
                   ->orderBy('r.name', 'ASC');
        if (in_array(HasDisable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.disabled = FALSE');
        }
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        return $qb;
    }

    /**
     * @return mixed
     * @throws \Doctrine\ORM\NonUniqueResultException
     */
    public function findOne()
    {
        $qb    = $this->createQueryBuilder('r')
                      ->orderBy('r.createdAt', 'DESC')
                      ->setMaxResults(1);
        if (in_array(IsSoftDeletable::class, $this->entity->getInterfaceNames())) {
            $qb->andWhere('r.deletedAt is NULL');
        }
        $query = $qb->getQuery();

        return $query->getOneOrNullResult();
    }
}
