<?php

namespace Velis\Di;

use Psr\SimpleCache\InvalidArgumentException;
use ReflectionClass;
use ReflectionException;
use Velis\App;
use Velis\App\User;
use Velis\Db\Db;
use Velis\Db\EntityRepository;
use Velis\Filesystem\FilesystemInterface;

/**
 * @author Jan Małysiak <jan.malysiak@velistech.com>
 */
trait ServiceResolverTrait
{
    /**
     * {@inheritDoc}
     * @throws InvalidArgumentException
     * @throws ReflectionException
     */
    public function get(string $name, $parameters = null)
    {
        if (User::class === $name) {
            return App::$user;
        }

        if (Db::class === $name) {
            return App::$di['db'];
        }

        if (FilesystemInterface::class === $name) {
            return App::$di->get('filesystem');
        }

        if ($this->isEntityRepository($name)) {
            return $this->getEntityRepository($name);
        }

        return parent::get($name, $parameters);
    }

    /**
     * @param string $name
     * @return bool
     */
    private function isEntityRepository(string $name): bool
    {
        if (!class_exists($name)) {
            return false;
        }

        $reflectionClass = new ReflectionClass($name);

        return $reflectionClass->isSubclassOf(EntityRepository::class);
    }

    /**
     * @param string $repositoryClass
     * @return EntityRepository
     * @throws InvalidArgumentException
     * @throws ReflectionException
     */
    private function getEntityRepository(string $repositoryClass): EntityRepository
    {
        $entityClass = preg_replace('/Repository(\\\\)?/', '', $repositoryClass);
        /** @var Db $db */
        $db = $this['db'];

        return $db->getRepository($entityClass);
    }
}
