<?php

/**
 * Class represents records from table admins
 * {autogenerated}
 * @property int $admin_id
 * @property string $login
 * @property string $name_f
 * @property string $name_l
 * @property string $pass
 * @property datetime $last_login
 * @property string $last_ip
 * @property string $last_session
 * @property string $email
 * @property int $super_user
 * @property string $perms
 * @property string $prefs
 * @property int $reseller_id
 * @see Am_Table
 */
class Admin extends Am_Record_WithData
{

    const PREF_DASHBOARD_WIDGETS = 'dashboard-widgets';
    const PREF_DASHBOARD_WIDGETS_CONFIG = 'dashboard-widgets-config';
    const PREF_REPORTS_SEND_FREQUENCY = 'reports-send-frequency';

    public function getName()
    {
        return trim($this->name_f . ' ' . $this->name_l);
    }
    public function checkPassword($pass)
    {
        $ph = new PasswordHash(8, true);
        return $pass && $ph->CheckPassword($pass, $this->pass);
    }

    public function setPass($pass)
    {
        $ph = new PasswordHash(12, true);
        $this->pass = $ph->HashPassword($pass);
    }

    public function hasPermission($perm, $priv = null)
    {
        if ($this->isSuper()) return true;
        if (empty($this->perms)) return false;
        $perms = $this->getPermissions();
        if (empty($perms[$perm]))
            return false;
        if ($priv === null)
            return true;
        if (is_array($perms[$perm]) && empty($perms[$perm][$priv]))
            return false;
        return true;
    }

    public function checkPermission($perm, $priv = null)
    {
        if (!$this->hasPermission($perm, $priv))
            throw new Am_Exception_AccessDenied(___("You have no permissions to perform requested operation"));
    }

    public function isAllowed($role = null, $resource = null, $privilege = null)
    {
        return $this->hasPermission($resource, $privilege);
    }

    public function setPermissions($perms)
    {
        $this->perms = json_encode($perms);
        $this->_perms = null;
    }

    public function getPermissions()
    {
        $_ = json_decode($this->get('perms'), true);
        $_[Am_Auth_Admin::PERM_LOGGED_IN] = 1;
        return $_;
    }

    public function setPreferences(array $prefs)
    {
        $this->prefs = serialize($prefs);
    }

    public function getPreferences()
    {
        return unserialize($this->prefs);
    }

    public function getPref($prefId, $default = null)
    {
        $prefs = $this->getPreferences();
        return (isset($prefs[$prefId]) ? $prefs[$prefId] : $default);
    }

    public function setPref($prefId, $value)
    {
        $prefs = $this->getPreferences();
        $prefs[$prefId] = $value;
        $this->setPreferences($prefs);
        $this->save();
    }

    public function isSuper()
    {
        return (bool) $this->super_user;
    }

    public function delete()
    {
        parent::delete();
        $this->getDi()->hook->call(Am_Event::ADMIN_AFTER_DELETE, ['admin'=>$this]);
    }
}

class AdminTable extends Am_Table_WithData
{

    protected $_key = 'admin_id';
    protected $_table = '?_admin';
    protected $_recordClass = 'Admin';

    function getAuthenticatedRow($login, $pass, & $code)
    {
        if (empty($login) || empty($pass))
        {
            $code = Am_Auth_Result::INVALID_INPUT;
            return;
        }
        $u = $this->getByLoginOrEmail($login);
        if (!$u)
        {
            $code = Am_Auth_Result::USER_NOT_FOUND;
            return;
        }
        if (!$u->checkPassword($pass))
        {
            $code = Am_Auth_Result::WRONG_CREDENTIALS;
            return;
        }
        $code = Am_Auth_Result::SUCCESS;
        return $u;
    }

    /**
     * Find admin record by email (if $login looks like an email)
     * or by username
     * @param string $login e-mail or username
     * @return Admin|null
     */
    function getByLoginOrEmail($login)
    {
        if (!strlen($login))
            return null;
        if (strpos($login, '@') !== false)
            return $this->findFirstByEmail($login);
        else
            return $this->findFirstByLogin($login);
    }
}