<?php

namespace Ulmus;

use Generator;

abstract class Ulmus
{
    public static string $repositoryClass = "\\Ulmus\\Repository";

    public static string $queryBuilderClass = "\\Ulmus\\QueryBuilder";

    public static ConnectionAdapter $defaultAdapter;

    public static Entity\ObjectInstanciator $objectInstanciator;
    
    public static array $resolved = [];

    public static function iterateQueryBuilder(QueryBuilder $queryBuilder, ?ConnectionAdapter $adapter = null) : Generator
    {
        $sql = $queryBuilder->render();
        $statement = ( $adapter ?: static::$defaultAdapter )->pdo->select($sql, $queryBuilder->parameters ?? []);

        while ( $row = $statement->fetch() ) {
            yield $row;
        }

        $statement->closeCursor();

        return [
            'count' => $statement->rowCount(),
        ];
    }
    
    public static function pdo(?ConnectionAdapter $adapter = null) : Common\PdoObject
    {
        return ( $adapter ?: static::$defaultAdapter )->pdo;
    }
    
    public static function runQuery(QueryBuilder $queryBuilder, ?ConnectionAdapter $adapter = null)
    {
        return static::pdo($adapter)->runQuery($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? []));
    }

    public static function resolveEntity(string $entityClass) : Common\EntityResolver
    {
        return static::$resolved[$entityClass] ?? static::$resolved[$entityClass] = new Common\EntityResolver($entityClass);
    }

    public static function repository(...$arguments) : Repository
    {
        return new static::$repositoryClass(...$arguments);
    }

    public static function queryBuilder(...$arguments) : QueryBuilder
    {
        return new static::$queryBuilderClass(...$arguments);
    }
    
    public static function instanciateObject(string $type, array $arguments) : object
    {
        return ( static::$objectInstanciator ?? static::$objectInstanciator = new Entity\ObjectInstanciator() )->instanciate($type, $arguments);
    }
        
    public static function convertObject(object $obj)
    {
        return ( static::$objectInstanciator ?? static::$objectInstanciator = new Entity\ObjectInstanciator() )->convert($obj);
    }
    
    protected static function fetchQueryBuilder(QueryBuilder $queryBuilder, ?ConnectionAdapter $adapter = null) : array
    {
        return ( $adapter ?: static::$defaultAdapter )->pdo->select($queryBuilder->render(), $queryBuilder->parameters ?? [])->fetchAll();
    }
}