<?php

namespace Application\Model\Repository;

use Ainias\Core\Model\Repository\StandardRepository;
use Doctrine\ORM\Internal\HydrationCompleteHandler;
use Doctrine\ORM\Query;
use Application\Controller\SyncController;
use Application\Model\Word;

class WordRepository extends StandardRepository
{
    /**
     * @param \DateTime $date
     * @param int $offset
     * @return array
     */
    public function findNewerThanDate($date, $offset = 0)
    {
        $queryBuilder = $this->_em->createQueryBuilder();
        $queryBuilder->select("w")->from(Word::class, "w");

        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.checked", "1"));
        if ($date != null)
        {
            $queryBuilder->andWhere($queryBuilder->expr()->gte("w.lastUpdated", ":fromDate"));
            $queryBuilder->setParameter("fromDate", $date->format("Y-m-d"));
        }
        $queryBuilder->setMaxResults(SyncController::SYNC_MAX_WORDS);
        $queryBuilder->setFirstResult($offset * SyncController::SYNC_MAX_WORDS);

        return $queryBuilder->getQuery()->getResult();
    }

    public function countNewerThanDate($date)
    {
        $queryBuilder = $this->_em->createQueryBuilder();
        $queryBuilder->select("COUNT(w.id) as number")->from(Word::class, "w");

        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.checked", "1"));
        if ($date != null)
        {
            $queryBuilder->andWhere($queryBuilder->expr()->gte("w.lastUpdated", ":fromDate"));
            $queryBuilder->setParameter("fromDate", $date->format("Y-m-d"));
        }
        return $queryBuilder->getQuery()->getSingleScalarResult();
    }

    public function getRandomWordNotChecked($minLength = 0, $maxLength = 100)
    {
        $numberWords = $this->countNotChecked($minLength, $maxLength);

        $queryBuilder = $this->_em->createQueryBuilder();
        $queryBuilder->select("w")->from(Word::class, "w");

        $offset = rand(0,$numberWords-1);

        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.checked", "0"));
        $queryBuilder->andWhere($queryBuilder->expr()->gte("CHAR_LENGTH(w.word)", ":minLength"));
        $queryBuilder->andWhere($queryBuilder->expr()->lte("CHAR_LENGTH(w.word)", ":maxLength"));
        $queryBuilder->setParameter("minLength", $minLength);
        $queryBuilder->setParameter("maxLength", $maxLength);
        $queryBuilder->setMaxResults(1);
        $queryBuilder->setFirstResult($offset);

        $res = $queryBuilder->getQuery()->getResult();
        if (is_array($res))
        {
            return $res[0];
        }
        return $res;
    }

    public function countNotChecked($minLength = 0, $maxLength = 100)
    {
        $queryBuilder = $this->_em->createQueryBuilder();
        $queryBuilder->select("COUNT(w.id)")->from(Word::class, "w");

//        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.word", "Sechsfüßer"));

        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.checked", "0"));
        $queryBuilder->andWhere($queryBuilder->expr()->gte("CHAR_LENGTH(w.word)", ":minLength"));
        $queryBuilder->andWhere($queryBuilder->expr()->lte("CHAR_LENGTH(w.word)", ":maxLength"));
        $queryBuilder->setParameter("minLength", $minLength);
        $queryBuilder->setParameter("maxLength", $maxLength);
        $queryBuilder->setMaxResults(1);
        return $queryBuilder->getQuery()->getSingleScalarResult();
    }

    public function countDeleted($minLength, $maxLength)
    {
        $queryBuilder = $this->_em->createQueryBuilder();
        $queryBuilder->select("COUNT(w.id)")->from(Word::class, "w");

        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.checked", "1"));
        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.deleted", "1"));
        $queryBuilder->andWhere($queryBuilder->expr()->gte("CHAR_LENGTH(w.word)", ":minLength"));
        $queryBuilder->andWhere($queryBuilder->expr()->lte("CHAR_LENGTH(w.word)", ":maxLength"));
        $queryBuilder->setParameter("minLength", $minLength);
        $queryBuilder->setParameter("maxLength", $maxLength);
        $queryBuilder->setMaxResults(1);
        return $queryBuilder->getQuery()->getSingleScalarResult();
    }

    public function countChecked($minLength, $maxLength)
    {
        $queryBuilder = $this->_em->createQueryBuilder();
        $queryBuilder->select("COUNT(w.id)")->from(Word::class, "w");

        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.checked", "1"));
        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.deleted", "0"));
        $queryBuilder->andWhere($queryBuilder->expr()->gte("CHAR_LENGTH(w.word)", ":minLength"));
        $queryBuilder->andWhere($queryBuilder->expr()->lte("CHAR_LENGTH(w.word)", ":maxLength"));
        $queryBuilder->setParameter("minLength", $minLength);
        $queryBuilder->setParameter("maxLength", $maxLength);
        $queryBuilder->setMaxResults(1);
        return $queryBuilder->getQuery()->getSingleScalarResult();
    }

    public function countUnsure($minLength, $maxLength)
    {
        $queryBuilder = $this->_em->createQueryBuilder();
        $queryBuilder->select("COUNT(w.id)")->from(Word::class, "w");

        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.checked", "-1"));
        $queryBuilder->andWhere($queryBuilder->expr()->gte("CHAR_LENGTH(w.word)", ":minLength"));
        $queryBuilder->andWhere($queryBuilder->expr()->lte("CHAR_LENGTH(w.word)", ":maxLength"));
        $queryBuilder->setParameter("minLength", $minLength);
        $queryBuilder->setParameter("maxLength", $maxLength);
        $queryBuilder->setMaxResults(1);
        return $queryBuilder->getQuery()->getSingleScalarResult();
    }

    public function findWordsForLength($length)
    {
        $queryBuilder = $this->_em->createQueryBuilder();
        $queryBuilder->select("w")->from(Word::class, "w");

        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.checked", "1"));
        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.deleted", "0"));
        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.used", "0"));
        $queryBuilder->andWhere($queryBuilder->expr()->eq("CHAR_LENGTH(w.word)", ":length"));
        $queryBuilder->setParameter("length", $length);
        return $queryBuilder->getQuery()->getResult();
    }

    public function countNotUsed(int $minLength, int $maxLength)
    {
        $queryBuilder = $this->_em->createQueryBuilder();
        $queryBuilder->select("COUNT(w.id)")->from(Word::class, "w");

        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.checked", "1"));
        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.deleted", "0"));
        $queryBuilder->andWhere($queryBuilder->expr()->eq("w.used", "0"));
        $queryBuilder->andWhere($queryBuilder->expr()->gte("CHAR_LENGTH(w.word)", ":minLength"));
        $queryBuilder->andWhere($queryBuilder->expr()->lte("CHAR_LENGTH(w.word)", ":maxLength"));
        $queryBuilder->setParameter("minLength", $minLength);
        $queryBuilder->setParameter("maxLength", $maxLength);
        $queryBuilder->setMaxResults(1);
        return $queryBuilder->getQuery()->getSingleScalarResult();
    }
}