<?php
namespace Core\Acl;
 
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\Exception\ServiceNotFoundException;
 
use Zend\Permissions\Acl\Acl;
use Zend\Permissions\Acl\Role\GenericRole as Role;
use Zend\Permissions\Acl\Resource\GenericResource as Resource;

use Zend\Db\Sql\Sql;
 
class BuilderDb implements ServiceManagerAwareInterface
{
	protected static $roles = array();
	
	protected static $resources = array();
	
	protected static $privileges = array();
	
    /**
     * @var ServiceManager
     */
    protected $serviceManager;
 
    /**
     * @param ServiceManager $serviceManager
     */
    public function setServiceManager(ServiceManager $serviceManager)
    {
        $this->serviceManager = $serviceManager;
        //return $this;
    }
 
    /**
     * Retrieve serviceManager instance
     *
     * @return ServiceLocatorInterface
     */
    public function getServiceManager()
    {
        return $this->serviceManager;
    }
 
    /**
     * Constroi a ACL
     * @return Acl 
     */
    public function build()
    {
        //$config = $this->getServiceManager()->get('Config');
		
        $acl = new Acl();
		
		$roles = $this->getRoles();
		
		foreach( $roles as $role )
		{
			$acl->addRole( new Role( $role['name'] ), $role['extend'] );
		}
		
		// ----------------------------------------------------------------------------------------

		$resources = $this->getResources();
		
		foreach( $resources as $resource )
		{
			 $acl->addResource( new Resource( $resource['path'] ) );
		}
		
		$privileges = $this->getPrivileges();
		
		foreach( $privileges as $privilege )
		{
			if( (boolean) $privilege['allow'] )
			{
				$acl->allow( $privilege['role'], $privilege['resource'] );
			}
			else
			{
				$acl->deny( $privilege['role'], $privilege['resource'] );
			}
		}
		
       /* foreach ($config['acl']['roles'] as $role => $parent) {
            $acl->addRole(new Role($role), $parent);
        }
        foreach ($config['acl']['resources'] as $r) {
            $acl->addResource(new Resource($r));
        }
        foreach ($config['acl']['privilege'] as $role => $privilege) {
            if (isset($privilege['allow'])) {
                foreach ($privilege['allow'] as $p) {
                    $acl->allow($role, $p);
                }
            }
            if (isset($privilege['deny'])) {
                foreach ($privilege['deny'] as $p) {
                    $acl->deny($role, $p);
                }
            }
        }*/
		
        return $acl;
    }
	
	/**
	 * Retorna os roles do sistema, que são pegos no banco
	 * @return array
	 */
	protected function getRoles()
	{
		if( empty( self::$roles ) )
		{
			$dbAdapter = $this->getServiceManager()->get('DbAdapter');

			$sql = new Sql( $dbAdapter );

			$select = $sql->select();
			
			$select	->columns(array( 'id', 'name' ))
					->from( array( 'ar1' => 'auth_roles' ) )
					->join(
						array( 'ar2' => 'auth_roles' ),
						'ar2.id = ar1.auth_role_id',
						array('extend' => 'name'),
						$select::JOIN_LEFT
					)
					->order('id ASC')
					;

			$statement = $sql->prepareStatementForSqlObject( $select );

			foreach( $statement->execute() as $role )
			{
				self::$roles[] = $role;
			}
		}
		
		return self::$roles;
	}
	
	/**
	 * Retorna os recursos
	 * @return Array
	 */
	protected function getResources()
	{
		if( empty( self::$resources ) )
		{
			$dbAdapter = $this->getServiceManager()->get('DbAdapter');

			$sql = new Sql( $dbAdapter );

			$select = $sql->select();
			
			$select	->columns(array( 'id', 'path' ))
					->from( 'auth_resources' )
					->order('id ASC')
					;

			$statement = $sql->prepareStatementForSqlObject( $select );

			foreach( $statement->execute() as $resource )
			{
				self::$resources[] = $resource;
			}
		}
		
		return self::$resources;
	}
	
	/**
	 * Retorna os privilegios dos roles
	 * @return Array
	 */
	protected function getPrivileges()
	{
		if( empty( self::$privileges ) )
		{
			$dbAdapter = $this->getServiceManager()->get('DbAdapter');

			$sql = new Sql( $dbAdapter );

			$select = $sql->select();
			
			$select	->columns(array( 'id', 'allow' ))
					->from( 'auth_privileges' )
					->join(
						'auth_roles',
						'auth_privileges.auth_role_id = auth_roles.id',
						array('role' => 'name'),
						$select::JOIN_INNER
					)
					->join(
						'auth_resources',
						'auth_privileges.auth_resource_id = auth_resources.id',
						array('resource' => 'path'),
						$select::JOIN_INNER
					)
					->order('id ASC')
					;

			$statement = $sql->prepareStatementForSqlObject( $select );

			foreach( $statement->execute() as $privileges )
			{
				self::$privileges[] = $privileges;
			}
		}
		
		return self::$privileges;
	}
}