<?php

namespace Keycloak;

use Keycloak\API\RoleMapper;
use Keycloak\API\Roles;
use Keycloak\API\Users;
use Keycloak\KeycloakUtil;

use CommonUtilities;

use Exception;
use Log;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Facades\Config;

class Keycloak {

    private $realm;
    private $openid_connect_discovery_url;
    private $client_id;
    private $client_secret;
    private $callback_url;
    private $cafile_path;
    private $verify_peer;
    private $base_endpoint_url;
    private $admin_username;
    private $admin_password;
    private $gateway_id;

    // API clients
    private $role_mapper;
    private $roles;
    private $users;

    /**
     * Constructor
     *
     */
    public function __construct($realm, $openid_connect_discovery_url, $client_id, $client_secret, $callback_url, $cafile_path, $verify_peer, $base_endpoint_url, $admin_username, $admin_password, $gateway_id) {

        $this->realm = $realm;
        $this->openid_connect_discovery_url = $openid_connect_discovery_url;
        $this->client_id = $client_id;
        $this->client_secret = $client_secret;
        $this->callback_url = $callback_url;
        $this->cafile_path = $cafile_path;
        $this->verify_peer = $verify_peer;
        $this->base_endpoint_url = $base_endpoint_url;
        $this->admin_username = $admin_username;
        $this->admin_password = $admin_password;
        $this->gateway_id = $gateway_id;

        $this->role_mapper = new RoleMapper($base_endpoint_url, $admin_username, $admin_password, $verify_peer, $this->cafile_path);
        $this->roles = new Roles($base_endpoint_url, $admin_username, $admin_password, $verify_peer, $this->cafile_path);
        $this->users = new Users($base_endpoint_url, $admin_username, $admin_password, $verify_peer, $this->cafile_path);
    }

    /**
     * Function to authenticate user
     *
     * @param string $username
     * @param string $password
     * @return boolean
     * @throws Exception
     */
     public function authenticate($username, $password){

        $config = $this->getOpenIDConnectDiscoveryConfiguration();
        $token_endpoint = $config->token_endpoint;

        // Init cUrl.
        $r = curl_init($token_endpoint);
        curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
        // Decode compressed responses.
        curl_setopt($r, CURLOPT_ENCODING, 1);
        curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
        if($this->verify_peer){
            curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path);
        }

        // Add client ID and client secret to the headers.
        curl_setopt($r, CURLOPT_HTTPHEADER, array(
            "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret),
        ));

        // Assemble POST parameters for the request.
        $post_fields = "client_id=" . urlencode($this->client_id) . "&client_secret=" . urlencode($this->client_secret) . "&grant_type=password";
        $post_fields .= "&username=" . urlencode($username) . "&password=" . urlencode($password);

        // Obtain and return the access token from the response.
        curl_setopt($r, CURLOPT_POST, true);
        curl_setopt($r, CURLOPT_POSTFIELDS, $post_fields);

        $response = curl_exec($r);
        if ($response == false) {
            die("curl_exec() failed. Error: " . curl_error($r));
        }

        //Parse JSON return object.
        $result = json_decode($response);
        // Log::debug("password grant type authenciation response", array($result));

        return $result;
     }

    public function getOAuthRequestCodeUrl($extra_params=null){
        $config = $this->getOpenIDConnectDiscoveryConfiguration();
        $authorization_endpoint = $config->authorization_endpoint;

        // TODO: add state variable to request and put into session
        $url = $authorization_endpoint . '?response_type=code&client_id=' . urlencode($this->client_id)
            . '&redirect_uri=' . urlencode($this->callback_url)
            . '&scope=openid';
        if ($extra_params != null) {
            $url = $url . '&' . $extra_params;
        }
        return $url;
    }

    public function getOAuthToken($code){

        $config = $this->getOpenIDConnectDiscoveryConfiguration();
        $token_endpoint = $config->token_endpoint;

        // Init cUrl.
        $r = curl_init($token_endpoint);
        curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
        // Decode compressed responses.
        curl_setopt($r, CURLOPT_ENCODING, 1);
        curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
        if($this->verify_peer){
            curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path);
        }

        // Add client ID and client secret to the headers.
        curl_setopt($r, CURLOPT_HTTPHEADER, array(
            "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret),
        ));

        // Assemble POST parameters for the request.
        $post_fields = "code=" . urlencode($code) . "&grant_type=authorization_code&redirect_uri=" . urlencode($this->callback_url);

        // Obtain and return the access token from the response.
        curl_setopt($r, CURLOPT_POST, true);
        curl_setopt($r, CURLOPT_POSTFIELDS, $post_fields);

        $response = curl_exec($r);
        if ($response == false) {
            die("curl_exec() failed. Error: " . curl_error($r));
        }

        //Parse JSON return object.
        $result = json_decode($response);
        Log::debug("getOAuthToken response", array($result));

        return $result;
    }

    public function getUserProfileFromOAuthToken($token){

        $config = $this->getOpenIDConnectDiscoveryConfiguration();
        $userinfo_endpoint = $config->userinfo_endpoint;

        $r = curl_init($userinfo_endpoint);
        curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
        // Decode compressed responses.
        curl_setopt($r, CURLOPT_ENCODING, 1);
        curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
        if($this->verify_peer){
            curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path);
        }
        curl_setopt($r, CURLOPT_HTTPHEADER, array(
            "Authorization: Bearer " . $token
        ));

        $response = curl_exec($r);
        if ($response == false) {
            die("curl_exec() failed. Error: " . curl_error($r));
        }

        //Parse JSON return object.
        $userinfo = json_decode($response);
        Log::debug("Keycloak userinfo", array($userinfo));
        $username = $userinfo->preferred_username;
        $firstname = $userinfo->given_name;
        $lastname = $userinfo->family_name;
        $email = $userinfo->email;

        // get roles from Keycloak API
        $role_mappings = $this->role_mapper->getRealmRoleMappingsForUser($this->realm, $userinfo->sub);
        $roles = [];
        foreach ($role_mappings as $role_mapping) {
            $roles[] = $role_mapping->name;
        }
        $roles = CommonUtilities::filterAiravataRoles($roles);
        return array('username'=>$username, 'firstname'=>$firstname, 'lastname'=>$lastname, 'email'=>$email, 'roles'=>$roles);
    }

    /**
     * Method to get refreshed access token
     * @param $refreshToken
     * @return mixed
     */
    public function getRefreshedOAuthToken($refresh_token){

        $config = $this->getOpenIDConnectDiscoveryConfiguration();
        $token_endpoint = $config->token_endpoint;

        // Init cUrl.
        $r = curl_init($token_endpoint);
        curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
        // Decode compressed responses.
        curl_setopt($r, CURLOPT_ENCODING, 1);
        curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
        if($this->verify_peer){
            curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path);
        }

        // Add client ID and client secret to the headers.
        curl_setopt($r, CURLOPT_HTTPHEADER, array(
            "Authorization: Basic " . base64_encode($this->client_id . ":" . $this->client_secret),
        ));

        // Assemble POST parameters for the request.
        $post_fields = "refresh_token=" . urlencode($refresh_token) . "&grant_type=refresh_token";

        // Obtain and return the access token from the response.
        curl_setopt($r, CURLOPT_POST, true);
        curl_setopt($r, CURLOPT_POSTFIELDS, $post_fields);

        $response = curl_exec($r);
        if ($response == false) {
            die("curl_exec() failed. Error: " . curl_error($r));
        }

        //Parse JSON return object.
        $result = json_decode($response);
        // Log::debug("getRefreshedOAuthToken response", array($result));

        return $result;
    }

    /**
     * Function to get the OAuth logout url
     */
    public function getOAuthLogoutUrl($redirect_uri) {
        $config = $this->getOpenIDConnectDiscoveryConfiguration();
        $logout_endpoint = $config->end_session_endpoint;
        return $logout_endpoint . '?redirect_uri=' . rawurlencode($redirect_uri);
    }

    /**
     * Function to list users
     *
     * @return Array of usernames
     */
    public function listUsers(){
        $users = $this->users->getUsers($this->realm);
        $usernames = [];
        foreach ($users as $user) {
            Log::debug("user", array($user));
            array_push($usernames, (object)["firstName"=>$user->firstName,"lastName"=>$user->lastName,"email"=>$user->email,"userEnabled"=>$user->enabled,"userName"=>$user->username]);
        }
        return $usernames;
    }

    /**
     * Function to search users
     * NOTE: Keycloak uses the keyword to search in the username, first and last
     * name and email address
     * @param $keyword
     * @return Array of usernames
     */
    public function searchUsers($phrase){
        $users = $this->users->searchUsers($this->realm, $phrase);
        $usernames = [];
        foreach ($users as $user) {
            array_push($usernames, (object)["firstName"=>$user->firstName,"lastName"=>$user->lastName,"email"=>$user->email,"userEnabled"=>$user->enabled,"userName"=>$user->username]);
        }
        return $usernames;
    }

    /**
     * Function to get the list of all existing roles
     * For Keycloak this is a list of "Realm roles"
     *
     * @return roles list
     */
    public function getAllRoles(){
        try {
            $roles = $this->roles->getRoles($this->realm);
            $role_names = [];
            foreach ($roles as $role) {
                $role_names[] = $role->name;
            }
            return CommonUtilities::filterAiravataRoles($role_names);
        } catch (Exception $ex) {
            throw new Exception("Unable to get all roles", 0, $ex);
        }
    }

    /**
     * Function to get roles of a user
     * For Keycloak this is a list of "Realm roles"
     *
     * @return array of role names
     */
    public function getUserRoles( $username ){
        try {
            // get userid from username
            $user_id = $this->getUserId($username);
            // Get the user's realm roles, then convert to an array of just names
            $roles = $this->role_mapper->getRealmRoleMappingsForUser($this->realm, $user_id);
            $role_names = [];
            foreach ($roles as $role) {
                $role_names[] = $role->name;
            }
            return CommonUtilities::filterAiravataRoles($role_names);
        } catch (Exception $ex) {
            throw new Exception("Unable to get User roles.", 0, $ex);
        }
    }

    /**
     * Function to update role list of user
     *
     * @param $username
     * @param $roles, an Array with two entries, "deleted" and "new", each of
     * which has a value of roles to be removed or added respectively
     * @return void
     */
    public function updateUserRoles( $username, $roles){
        // Log::debug("updateUserRoles", array($user_id, $roles));
        try {
            // get userid from username
            $user_id = $this->getUserId($username);
            // Get all of the roles into an array keyed by role name
            $all_roles = $this->roles->getRoles($this->realm);
            $roles_by_name = [];
            foreach ($all_roles as $role) {
                $roles_by_name[$role->name] = $role;
            }

            // Process the role deletions
            if(isset($roles["deleted"])){
                if(!is_array($roles["deleted"]))
                    $roles["deleted"] = array($roles["deleted"]);
                foreach ($roles["deleted"] as $role) {
                    $this->role_mapper->deleteRealmRoleMappingsToUser($this->realm, $user_id, array($roles_by_name[$role]));
                }
            }

            // Process the role additions
            if(isset($roles["new"])){
                if(!is_array($roles["new"]))
                    $roles["new"] = array($roles["new"]);
                foreach ($roles["new"] as $role) {
                    $this->role_mapper->addRealmRoleMappingsToUser($this->realm, $user_id, array($roles_by_name[$role]));
                }
            }
        } catch (Exception $ex) {
            throw new Exception("Unable to update role of the user.", 0, $ex);
        }
    }

    /**
     * Function to get the user profile of a user
     * @param $username
     */
    public function getUserProfile($username){
        $user = $this->users->getUserByUsername($this->realm, $username);
        if($user != null){
            $result = [];
            $result["email"] = $user->email;
            $result["firstname"] = $user->firstName;
            $result["lastname"] = $user->lastName;
            $result["userEnabled"] = $user->enabled;
            return $result;
        }else{
            return [];
        }

    }

    /**
     * Function to check whether a user exists with the given userId
     * @param $username
     * @return bool
     */
    public function usernameExists($username){
        try{
            $user = $this->users->getUserByUsername($this->realm, $username);
            return $user != null;
        }catch (Exception $ex){
            // Username does not exists
            return false;
        }
    }

    // TODO: move this to IamAdminServices
    public function isUpdatePasswordRequired($username) {

        try{
            $user = $this->users->getUserByUsername($this->realm, $username);
            if ($user != null) {
                return in_array("UPDATE_PASSWORD", $user->requiredActions);
            } else {
                return false;
            }
        }catch (Exception $ex){
            // Username does not exists
            return false;
        }
    }

    public function getAdminAuthzToken() {

        $access_token = KeycloakUtil::getAPIAccessToken($this->base_endpoint_url, $this->realm, $this->admin_username, $this->admin_password, $this->verify_peer, $this->cafile_path);
        $authzToken = new \Airavata\Model\Security\AuthzToken();
        $authzToken->accessToken = $access_token;
        $authzToken->claimsMap['gatewayID'] = $this->gateway_id;
        $authzToken->claimsMap['userName'] = $this->admin_username;
        return $authzToken;
    }

    /**
     * Get the user's Keycloak user_id from their username
     */
    private function getUserId($username) {
        $user = $this->users->getUserByUsername($this->realm, $username);
        if ($user != null) {
            return $user->id;
        } else {
            throw new Exception("No user found with username $username");
        }
    }

    private function getOpenIDConnectDiscoveryConfiguration() {

        // TODO: cache the result of the request
        $r = curl_init($this->openid_connect_discovery_url);
        curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
        // Decode compressed responses.
        curl_setopt($r, CURLOPT_ENCODING, 1);
        curl_setopt($r, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
        if($this->verify_peer){
            curl_setopt($r, CURLOPT_CAINFO, $this->cafile_path);
        }

        $result = curl_exec($r);
        if ($result == false) {
            die("curl_exec() failed. Error: " . curl_error($r));
        }

        $json = json_decode($result);

        // Log::debug("openid connect discovery configuration", array($json));
        return $json;
    }
}

