<?php

namespace Velis\Bpm;

use Exception;
use ReflectionException;
use Velis\Arrays;
use Velis\Bpm\Resource\Service;
use Velis\Model\Cacheable;
use Velis\Model\DataObject;
use Velis\Model\Hierarchical;

/**
 * Resource model
 *
 * @author Bartosz Izdebski <bartosz.izdebski@velis.pl>
 * @author Olek Procki <olo@velis.pl>
 */
class Resource extends DataObject implements Cacheable
{
    /**
     * Buffer for not cached model type (must be redeclared in Cacheable class)
     * @var Hierarchical[]
     */
    protected static $_source;


    /**
     * Default list order
     * @var string
     */
    protected static $_listDefaultOrder = 'name';


    /**
     * @var bool
     */
    protected static $_filterListParams = true;


    /**
     * Resource services
     * @var Service[]
     */
    protected $_services;


    /**
     * @return string
     */
    protected function _getTableName()
    {
        return 'app.resource_tab';
    }


    /**
     * Returns resource name
     * @return string
     */
    public function getName()
    {
        return $this['name'];
    }


    /**
     * Returns resource services
     * @return Service[]
     * @throws ReflectionException
     */
    public function getServices()
    {
        if (!isset($this->_services)) {
            self::loadItemsServices([$this]);
        }

        return $this->_services;
    }


    /**
     * Returns list of active resources
     * @param bool $loadServices
     * @return static[]
     * @throws ReflectionException
     */
    public static function listActive($loadServices = false)
    {
        $activeResources = [];

        foreach (self::listCached() as $resource) {
            if (!$resource->active) {
                continue;
            }
            $activeResources[$resource->id()] = $resource;
        }

        if ($loadServices) {
            self::loadItemsServices($activeResources);
        }

        return $activeResources;
    }


    /**
     * Removes resource
     * @return bool
     * @throws Exception
     */
    public function remove()
    {
        self::$_db->startTrans();

        try {
            if (self::$_db->tableExists('app.resource_service_tab')) {
                self::$_db->execDML(
                    "DELETE FROM app.resource_service_tab WHERE resource_id = :resource_id",
                    ['resource_id' => $this->id()]
                );
            }
            $result = parent::_remove();

            self::$_db->commit();

            return $result;
        } catch (Exception $e) {
            self::$_db->rollback();
            throw $e;
        }
    }


    /**
     * Loads items services at once
     * @param Resource[] $items
     * @throws ReflectionException
     */
    public static function loadItemsServices($items)
    {
        if ($idList = self::getCollectionIds($items)) {
            foreach (Service::listAll(['resource_id' => $idList]) as $service) {
                foreach ($items as $resource) {
                    if (!isset($resource->_services)) {
                        $resource->_services = array();
                    }
                    if ($resource->id() == $service->resource_id) {
                        $resource->_services[$service->id()] = $service;
                    }
                }
            }
        }
    }


    /**
     * List resources available for reservations
     * @return static[]
     * @throws ReflectionException
     */
    public static function listForReservations()
    {
        $activeResources = self::listActive();

        return Arrays::byValue($activeResources, 'reservation_available', 1);
    }
}
