/// <summary>
        /// Initializes a new instance of the <see cref="WrikeClient"/> class.
        /// </summary>
        /// <param name="accessTokenRequest"></param>
        /// <param name="redirectUri">Must provide if used in authorization url</param>
        /// <param name="customHttpClient">Custom implementation of HttpClient.
        /// Commonly used to add throttling to the number of requests made to the Wrike API</param>
        public WrikeClient(WrikeAccessTokenRequest accessTokenRequest, string redirectUri, HttpClient customHttpClient = null)
        {
            if (accessTokenRequest == null)
            {
                throw new ArgumentException(nameof(accessTokenRequest));
            }

            if (redirectUri == null)
            {
                throw new ArgumentNullException(nameof(redirectUri));
            }

            if (redirectUri.Trim() == string.Empty)
            {
                throw new ArgumentException("value can not be empty", nameof(redirectUri));
            }

            var accessTokenResponse = GetAccesToken(accessTokenRequest, redirectUri);

            _clientId     = accessTokenRequest.ClientId;
            _clientSecret = accessTokenRequest.ClientSecret;
            _redirectUri  = redirectUri;
            _refreshToken = accessTokenResponse.RefreshToken;
            _bearerToken  = accessTokenResponse.AccessToken;
            _host         = accessTokenResponse.Host;

            InitializeHttpClient(customHttpClient);
        }
        /// <summary>
        /// Request access credentials
        /// </summary>
        /// <param name="accessTokenRequest"></param>
        /// <param name="redirectUri"></param>
        /// See <see href="https://developers.wrike.com/documentation/oauth2"/>
        public static WrikeAccessTokenResponse GetAccesToken(WrikeAccessTokenRequest accessTokenRequest, string redirectUri)
        {
            if (accessTokenRequest == null)
            {
                throw new ArgumentNullException(nameof(accessTokenRequest));
            }

            var parameters = GetNameValueCollection(accessTokenRequest.ClientId, accessTokenRequest.ClientSecret,
                                                    accessTokenRequest.AuthorizationCode, accessTokenRequest.GrantType);

            parameters.Add("redirect_uri", redirectUri);

            var response = string.Empty;

            using (var webClient = new WebClient())
            {
                try
                {
                    var responseBytes = webClient.UploadValues("https://www.wrike.com/oauth2/token", "POST",
                                                               parameters);
                    response = webClient.Encoding.GetString(responseBytes);
                }
                catch (WebException exception)
                {
                    using (var reader = new StreamReader(exception.Response.GetResponseStream()))
                    {
                        var errorResponse = reader.ReadToEnd();
                        var er            = JsonConvert.DeserializeAnonymousType(errorResponse, new { error = "", error_description = "" });
                        throw new WrikeApiException(er.error, er.error_description);
                    }
                }
            }

            return(JsonConvert.DeserializeObject <WrikeAccessTokenResponse>(response));
        }