<?php

/**
 * ServiceProviders token database handler
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is protected by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2014 Lifestyle Webconsulting GmbH
 * @version    $Id:$
 * @link       http://www.life-style.de
 */

namespace Sso\ApiBundle\Database\ServiceProvider;

use LifeStyle\Tools\CredentialsBundle\Entity\Token as ServiceProviderToken;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\NonUniqueResultException;

/**
 * ServiceProviders token database handler
 */
class Token extends Base
{
    /**
     * List of all tokens
     *
     * @return array
     */
    public function getAll()
    {
        return $this->_entityManager->getRepository('LifeStyle\Tools\CredentialsBundle\Entity\Token')->findAll();
    }

    /**
     * List of all tokens
     * @return array
     */
    public function getOneById($token)
    {
        return $this->_entityManager->getRepository('LifeStyle\Tools\CredentialsBundle\Entity\Token')
            ->findOneBy(['ServiceToken' => $token]);
    }

    /**
     * Save token from data array
     *
     * @param array $data
     */
    public function saveTokenFromArray($data)
    {
        $model = new ServiceProviderToken();
        $model->setServiceToken($data['ServiceToken']);
        $model->setServiceToken2Ip($data['ServiceToken2Ip']);
        $model->setAllowedCallsPerDay((int)$data['AllowedCallsPerDay']);
        $model->setValidUntil(new DateTime($data['ValidUntil']));
        $model->setBlocked((int)$data['Blocked']);

        $this->saveToken($model);
    }

    /**
     * Save token
     *
     * @param \Sso\ApiBundle\Entity\ServiceProvider\Type\Token $model
     * @return boolean
     */
    public function saveToken(ServiceProviderToken $model)
    {
        $this->_entityManager->persist($model);
        $this->_entityManager->flush($model);
    }

    /**
     *
     * @param ServiceProviderToken $model
     */
    public function deleteToken(ServiceProviderToken $model)
    {
        $this->_entityManager->remove($model);
        $this->_entityManager->flush($model);
    }

    /**
     *
     * @param string $ServiceToken
     * @return ServiceProviderToken|null
     * @throws \Exception
     */
    public function credentialsGetActiveToken($ServiceToken)
    {
        $dql = 'SELECT t FROM LifeStyle\Tools\CredentialsBundle\Entity\Token t '
            . 'WHERE t.ServiceToken=:ServiceToken '
            . 'AND t.Blocked=:Blocked '
            . 'AND t.ValidUntil>CURRENT_DATE()';
        $query = $this->_entityManager->createQuery($dql);
        $query->setParameters(array(
            'ServiceToken' => (string)$ServiceToken,
            'Blocked' => 0,
        ));

        try {
            $tokenModel = $query->getSingleResult();
        } catch (\Exception $e) {

            // Token not found or too many rows
            if ($e instanceof NoResultException || $e instanceof NonUniqueResultException) {
                return null;
            }

            // An unexpected error
            throw $e;
        }
        return $tokenModel;
    }

    /**
     * Find user by token by id
     *
     * @param string $tokenId
     * @return ModelToken|null
     */
    public function getTokenByToken($token)
    {
        return $this->getRepository()->findOneBy(array('ServiceToken' => $token));
    }

    /**
     *
     * @return \Doctrine\ORM\EntityRepository
     */
    public function getRepository()
    {
        return $this->_entityManager->getRepository('LifeStyle\Tools\CredentialsBundle\Entity\Token');
    }


    /**
     * @param $serviceNameId
     * @return array
     */
    public function getByServiceNameId($serviceNameId)
    {
        $dql = 'SELECT a FROM LifeStyle\Tools\CredentialsBundle\Entity\Token a '
            . 'JOIN a.ServiceNames sn '
            . 'WHERE sn.ServiceNameId=:ServiceNameId ';
        $query = $this->_entityManager->createQuery($dql);

        $query->setParameters(array(
            'ServiceNameId' => (string)$serviceNameId
        ));

        return $query->getResult();
    }

    /**
     * @param string $serviceNameId
     * @return array
     */
    public function getNotAssignedByServiceNameId($serviceNameId)
    {
        $allTokens = $this->_entityManager->getRepository('LifeStyle\Tools\CredentialsBundle\Entity\Token')
            ->findAll();

        // filter out all tokens that currently do not have the given ServiceNameId assigned to them
        $tokens = [];
        foreach ($allTokens as $aToken) {
            if ($aToken->getServiceNames()->count() == 0) {
                $tokens[] = $aToken;
            } else {
                $hasServiceNameId = false;
                foreach ($aToken->getServiceNames() as $tokenServiceName) {
                    if ($tokenServiceName->getServiceNameId() == $serviceNameId) {
                        $hasServiceNameId = true;
                    }
                }
                if (!$hasServiceNameId) {
                    $tokens[] = $aToken;
                }
            }
        }

        return $tokens;
    }

    /**
     * @param string $tokenId
     * @param string $serviceNameId
     * @return bool
     */
    public function addToServiceName($tokenId, $serviceNameId)
    {
        if ((null === $tokenId) || (null === $serviceNameId)) {
            return false;
        }

        $serviceName = $this->_entityManager->getRepository('LifeStyle\Tools\CredentialsBundle\Entity\ServiceName')->findOneBy(['ServiceNameId' => $serviceNameId]);
        $token = $this->_entityManager->getRepository('LifeStyle\Tools\CredentialsBundle\Entity\Token')->findOneBy(['ServiceToken' => $tokenId]);
        $token->addServiceName($serviceName);
        $this->_entityManager->persist($serviceName);
        $this->_entityManager->flush();
        return true;
    }

    /**
     * @param string $serviceToken
     * @param string $serviceNameId
     * @return bool
     */
    public function removeFromServiceName($serviceToken, $serviceNameId)
    {
        $serviceName = $this->_entityManager->getRepository('LifeStyle\Tools\CredentialsBundle\Entity\ServiceName')->findOneBy(['ServiceNameId' => $serviceNameId]);
        $token = $this->_entityManager->getRepository('LifeStyle\Tools\CredentialsBundle\Entity\Token')->findOneBy(['ServiceToken' => $serviceToken]);
        $token->removeServiceName($serviceName);
        $this->_entityManager->persist($serviceName);
        $this->_entityManager->flush();
        return true;
    }
}
