<?php
namespace Incoviba\common;

use Incoviba\Common\Alias\OldModel as Model;
use Incoviba\Common\Factory\Model as Factory;

/**
 *
 * @author Aldarien
 * @property int $id
 * @property string $description length=50
 * @property int $level
 * @property Role $inherits
 *
 */
class Role extends Model
{
  public static $_table = 'roles';

  public function inherits()
  {
    if ($this->inherits != 0) {
      return $this->belongsTo(Role::class, 'inherits')->findOne();
    }
    return false;
  }
  protected $permissions;
  public function permissions()
  {
    if ($this->permissions == null) {
      $permissions = $this->hasMany(Permission::class, 'ext_id')->where('permissions.type', 2)->findMany();
      if ($this->inherits()) {
        $permissions = array_merge($permissions, $this->inherits()->permissions());
      }
      usort($permissions, function($a, $b) {
        return strcmp($a->action()->description, $b->action()->description);
      });
      $this->permissions = $permissions;
    }
    return $this->permissions;
  }
  public function users()
  {
  	return $this->hasManyThrough(User::class, UserRole::class, 'role', 'user')->findMany();
  }
  public function hasAccess($route)
  {
    $action = $route->getArgument('action');
    $action = (new Factory(Action::class))->where(['description' => $action])->find();
    if (!$action) {
      return false;
    }

    $data = [
      'type' => 2,
      'ext_id' => $this->id,
      'action_id' => $action->id,
      'status' => 1
    ];
    $permission = (new Factory(Permission::class))->where($data)->find();
  	if ($permission !== false) {
  		return true;
  	}

    if ($this->inherits()) {
      return $this->inherits()->hasAccess($route);
    }
    return false;
  }
  public function checkAccess($action_name)
  {
    $action = (new Factory(Action::class))->where(['description' => $action_name])->find();
    if (!$action) {
      throw new \Exception('Action ' . $action_name . ' not found.');
    }
    $permission = (new Factory(Permission::class))->where([
      'type' => 2,
      'ext_id' => $this->id,
      'action_id' => $action->id,
      'status' => 1
    ])->find();
  	if ($permission !== false) {
  		return true;
  	}
    if ($this->inherits()) {
      return $this->inherits()->checkAccess($action_name);
    }
    return false;
  }
  public function addPermission($action_name)
  {
    if ($this->checkAccess($action_name)) {
      return;
    }
    $action = (new Factory(Action::class))->where(['description' => $action_name])->find();
    if (!$action) {
      throw new \InvalidArgumentException($action_name . ' not found.');
    }
    $data = [
      'type' => 2,
      'ext_id' => $this->id,
      'action_id' => $action->id
    ];
    $permission = (new Factory(Permission::class))->where($data)->find();
    if (!$permission) {
      $permission = (new Factory(Permission::class))->create($data);
    }
    $permission->status = 1;
    $permission->save();
  }
  public function removePermission($action_name)
  {
    if (!$this->checkAccess($action_name)) {
      return;
    }
    $action = (new Factory(Action::class))->where(['description' => $action_name])->find();
    if (!$action) {
      throw new \InvalidArgumentException($action_name . ' not found.');
    }
    $data = [
      'type' => 2,
      'ext_id' => $this->id,
      'action_id' => $action->id
    ];
    $permission = (new Factory(Permission::class))->where($data)->find();
    if (!$permission) {
      return;
    }
    $permission->status = 0;
    $permission->save();
  }
  public function hasUser($user)
  {
    $user = \Model::factory(User::class)
      ->select('users.*')
      ->join('user_roles', ['user_roles.user', '=', 'users.id'])
      ->join('roles', ['roles.id', '=', 'user_roles.role'])
      ->where('roles.id', $this->id)
      ->whereAnyIs([['users.name' => $user], ['users.id' => $user]])
      ->findOne();
    if ($user !== false) {
      return true;
    }
    return false;
  }
  public function isInherited($action_name)
  {
    if (!$this->checkAccess($action_name)) {
      return false;
    }
    $action = (new Factory(Action::class))->where(['description' => $action_name])->find();
    $permission = (new Factory(Permission::class))->where([
      'type' => 2,
      'ext_id' => $this->id,
      'action_id' => $action->id,
      'status' => 1
    ])->find();
  	if ($permission !== false) {
  		return false;
  	}
    return true;
  }
}
?>
