<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

/**
 * OAuthOffice365
 */
class OAuthOffice365 {
    
    /**
     * options
     *
     * @var undefined
     */
    private $options;
    
    /**
     * __construct
     *
     * @param  mixed $options
     * @return void
     */
    public function __construct( $options = array() ) {
        $this->options = $options;
    } 
    
    /**
     * getOffice365AuthURL
     *
     * @param  mixed $options
     * @return void
     */
    public function getOffice365AuthURL( $options = array() ) {
        $base   = $this->options['urlAuthorize'];

        $params = $this->getOffice365AuthParams( $options );
        $query  = $this->getAuthEncodedQuery( $params );

        return $this->attachQuery( $base, $query );
    }
    
    /**
     * getOffice365AuthParams
     *
     * @param  mixed $options
     * @return void
     */
    private function getOffice365AuthParams( $options ) {
    
        if (empty( $options['scope']) ) {
            $options['scope'] = $this->options['scopes'];
        }

        $options += [
            'response_type'   => 'code',
            'approval_prompt' => 'auto'
        ];

        if (is_array($options['scope'])) {
            $separator = ',';
            $options['scope'] = implode($separator, $options['scope']);
        }

        // Business code layer might set a different redirect_uri parameter
        // depending on the context, leave it as-is
        if (!isset($options['redirect_uri'])) {
            $options['redirect_uri'] = $this->options['redirectUri'];
        }

        $options['client_id'] = $this->options['clientId'];
       
        return $options;
    }
    
    /**
     * getAuthEncodedQuery
     *
     * @param  mixed $params
     * @return void
     */
    protected function getAuthEncodedQuery( array $params ) {
        return $this->GenerateSerializeQuery($params);
    }
    
    /**
     * GenerateSerializeQuery
     *
     * @param  mixed $params
     * @return void
     */
    protected function GenerateSerializeQuery( array $params ) {
        return http_build_query($params, '', '&', \PHP_QUERY_RFC3986);
    }
    
    /**
     * attachQuery
     *
     * @param  mixed $url
     * @param  mixed $query
     * @return void
     */
    protected function attachQuery( $url, $query ) {
        $query = trim($query, '?&');

        if ($query) {
            $glue = strstr($url, '?') === false ? '?' : '&';
            return $url . $glue . $query;
        }

        return $url;
    }
    
    /**
     * getOffice365AccessToken
     *
     * @param  mixed $grant
     * @param  mixed $options
     * @return void
     */
    public function getOffice365AccessToken( $grant, array $options = [] ) {
        $params = [
            'client_id'     => $this->options['clientId'],
            'client_secret' => $this->options['clientSecret'],
            'redirect_uri'  => $this->options['redirectUri'],
            'grant_type' => $grant,
        ];
        
        $params += $options;
       
        $requestData = $this->office365GetAccessTokenRequest($params);
        
        $response = wp_remote_request($requestData['url'], $requestData['params']);
        
        if (is_wp_error($response)) {
            throw new \Exception(
                $response->get_error_message()
            );
        }

        $responseBody = wp_remote_retrieve_body($response);

        if (false === is_array($response)) {
            throw new \Exception(
                'Invalid response received from Authorization Server. Expected JSON.'
            );
        }

        if(empty(['access_token'])) {
            throw new \Exception(
                'Invalid response received from Authorization Server.'
            );
        }

        return \json_decode($responseBody, true);
    }
    
    /**
     * office365GetAccessTokenRequest
     *
     * @param  mixed $params
     * @return void
     */
    protected function office365GetAccessTokenRequest( $params ) {
        $method  = "POST";
        $url     = $this->getOffice365AccessTokenUrl($params);
        $options = $this->GenerateSerializeQuery($params);
        
        return [
            'url' => $url,
            'params' => [
                'method' => $method,
                'body' => $options,
                'headers' => [
                    'content-type' => 'application/x-www-form-urlencoded'
                ]
            ]
        ];
    }
    
    /**
     * getOffice365AccessTokenUrl
     *
     * @param  mixed $params
     * @return void
     */
    protected function getOffice365AccessTokenUrl( $params ) {
        $url = $this->options['urlAccessToken'];
        return $url;
    }
    
    /**
     * getAccessTokenQuery
     *
     * @param  mixed $params
     * @return void
     */
    protected function getAccessTokenQuery( array $params ) {
        return $this->GenerateSerializeQuery($params);
    }
}
