<?php

/**
 * user class contains username and its roles
 * This class is used in the base class
 *
 * @author hahn
 */
class user {
    
    /**
     * login name of the current user
     * @var string
     */
    private $_sUsername=false;
    
    /**
     * list of groups of the current user
     * @var array
     */
    private $_aUserGroups=array();
    
    /**
     * list of roles based on the groups
     * @var array
     */
    private $_aUserPermmissions=array();
    
    /**
     * list of projects the current user is involved in
     * @var array
     */
    private $_aProjects=array();
    
    /**
     * name of the last checked role
     * @var string
     */
    private $_sLastCheckedPermission=false;
    
    /**
     * init user with optional given user
     * @param type $sUser
     */
    public function __construct($sUser=false){
        $this->setUser($sUser);
    }
    
    
    // ----------------------------------------------------------------------
    // private functions
    // ----------------------------------------------------------------------
    
    
    /**
     * detect a user
     * @return type
     */
    private function _autoDetectUser(){
        $sUser=false;
        if (isset($_SESSION) && is_array($_SESSION) && array_key_exists("PHP_AUTH_USER", $_SESSION)){
            $sUser=$_SESSION["PHP_AUTH_USER"];
        }
        if (!$sUser && is_array($_SERVER) && array_key_exists("PHP_AUTH_USER", $_SERVER)){
            $sUser=$_SERVER["PHP_AUTH_USER"];
        }
        if (php_sapi_name() == "cli") {
            $sUser="cliadmin";
        }
        return $sUser;
    }

    // UNUSED SO FAR
    private function _getUser2Projects(){
        return require(__DIR__ . '/../../../config/inc_user2projects.php');
    }
    
    private function _getUser2Roles(){
        return require(__DIR__ . '/../../../config/inc_user2roles.php');
    }
    /**
     * TODO: reimplement
     * get the user groups of the current user from an internal source.
     * The function returns a flat aray with names of the groups
     * @return array
     */
    private function _getUserGroups(){
        $aGroups=array();
        if ($this->_sUsername){
            $aGroups[]="authenticated";
            // $aGroups[]='#'.$this->_sUsername;
            $aUserDefinitions=$this->_getUser2Roles();
            foreach (array_keys($aUserDefinitions) as $sGroup){
                if (array_search($this->_sUsername, $aUserDefinitions[$sGroup])!==false){
                    $aGroups[]=$sGroup;
                }
            }
        }
        $this->_aUserGroups=$aGroups;
        return $this->_aUserGroups;
    }

    /**
     * TODO: reimplement
     * get the user roles of the current user from an internal source.
     * The function returns a flat aray with names of the roles
     * @return array
     */
    private function _getUserPermission(){
        $aRoles=array();
        $aRolesDefinitions=require(__DIR__ . '/../../../config/inc_roles.php');

        // anonymous roles:
        $aRoles=array_merge($aRoles, $aRolesDefinitions['all']);
        
        foreach (array_keys($aRolesDefinitions) as $sGroup){
            if ($this->hasGroup($sGroup)){
                $aRoles=array_merge($aRoles, $aRolesDefinitions[$sGroup]);
            }
        }
        
        $this->_aUserPermmissions=  array_unique($aRoles);
        return $this->_aUserPermmissions;
    }
    
    
    // ----------------------------------------------------------------------
    // public ACTIONS
    // ----------------------------------------------------------------------
    
    
    /**
     * authenticate a user with the configured methods
     * @global array  $aConfig  global config
     * @global array  $aParams  params (i.e. GET and POST)
     * @return boolean
     */
    public function authenticate(){
        global $aConfig, $aParams;
        
        if(!array_key_exists('auth', $aConfig) || !count($aConfig['auth']) || !array_key_exists('user', $aParams)){
            return false;
        }
        $sUser=$aParams['user'];
        $sPassword=array_key_exists('password', $aParams)?$aParams['password']:false;

        foreach (array_keys($aConfig['auth']) as $sAuthMethod){
            $oUserAuth=false;
            switch ($sAuthMethod){
                case 'ldap':
                    require_once("userauth.ldap.class.php");
                    $oUserAuth=new userauthLdap($aConfig['auth']['ldap']);
                    break;
                // implement other methods here
                // see userauth.ldap.class.php as simple example
                    
                default:
                    echo 'WARNING: authmethod '.$sAuthMethod.' in your config is not implemented in '.basename(__FILE__).' and is useless so far.<br>';
            }
            // if authentication fails then continue and try next method
            if ($oUserAuth && $oUserAuth->authenticate($sUser, $sPassword)){
                
                // set a session - it must correspondent with _autoDetectUser()
                $_SESSION["PHP_AUTH_USER"]=$sUser;
                $this->setUser();
                return true;
            }
        }
        return false;
    }

    /**
     * logoff user
     * @return boolean
     */
    public function logoff(){
        unset($_SESSION["PHP_AUTH_USER"]);
        $this->setUser();
        return true;
    }
    
    /**
     * set a authenticated user and get its roles
     */
    public function setUser(){
        $this->_sUsername=$this->_autoDetectUser();
        $this->_getUserGroups();
        $this->_getUserPermission();
    }
    
    /**
     * return html code to display a denied message
     * @return type
     */
    public function showDenied(){
        return '<div class="alert alert-danger" role="alert">'
        . ($this->_sUsername ? ' User: '.$this->_sUsername : ''
            ? t("class-user-error-deny-no-role").'<br>('.$this->_sLastCheckedPermission.')'
            : t("class-user-error-login-required")
        )
        . '</div><br>'
        . '<a href="/deployment/all/login/" class="btn btn-primary">'.t('menu-login').'</a>'
        ;
    }
    
    // ----------------------------------------------------------------------
    // public GETTER
    // ----------------------------------------------------------------------

    
    // UNUSED SO FAR
    public function getUser2Projects(){
        return $this->_getUser2Projects();
    }
    
    public function getUser2Roles(){
        return $this->_getUser2Roles();
    }

    /**
     * get the current username
     * @return string
     */
    public function getUsername(){
        return $this->_sUsername;
    }
    /**
     * get a flat array with roles of the current user
     * @return string
     */
    public function getUserGroups(){
        return $this->_aUserGroups;
    }
    /**
     * get a flat array with roles of the current user
     * @return string
     */
    public function getUserPermission(){
        return $this->_aUserPermmissions;
    }

    /**
     * check if the current user has a given role name
     * @param string  $sGroupname  name of the role to check
     * @return type
     */
    public function hasGroup($sGroupname){
        return (array_search($sGroupname, $this->_aUserGroups)!==false);
    }
    /**
     * check if the current user has a given role name
     * @param string  $sPermission  name of the role to check
     * @return type
     */
    public function hasPermission($sPermission){
        $this->_sLastCheckedPermission=$sPermission;
        $bReturn=array_search($sPermission, $this->_aUserPermmissions)!==false;
        // $this->log(__FUNCTION__ . "($sRolename) -> " . $bReturn ? 'true' : 'false');
        return $bReturn;
    }

    
}
