private async Task <IEnumerable <TSchema> > GetCustomSearch <TSchema>(string query, Toolkit.Services.IParser <TSchema> parser)
            where TSchema : Toolkit.Services.SchemaBase
        {
            try
            {
                var uri = new Uri($"{BaseUrl}/{query}");

                TwitterOAuthRequest request = new TwitterOAuthRequest();
                var rawResult = await request.ExecuteGetAsync(uri, _tokens);

                return(parser.Parse(rawResult));
            }
            catch (WebException wex)
            {
                HttpWebResponse response = wex.Response as HttpWebResponse;
                if (response != null)
                {
                    if ((int)response.StatusCode == 429)
                    {
                        throw new TooManyRequestsException();
                    }

                    if (response.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        throw new OAuthKeysRevokedException();
                    }
                }

                throw;
            }
        }
        /// <summary>
        /// Get home time line data.
        /// </summary>
        /// <typeparam name="TSchema">Strong typed result.</typeparam>
        /// <param name="maxRecords">Upper record limit.</param>
        /// <param name="parser">Specific result parser.</param>
        /// <returns>Return strong typed list of results.</returns>
        private async Task <IEnumerable <TSchema> > GetHomeTimeLineAsync <TSchema>(int maxRecords, Toolkit.Services.IParser <TSchema> parser)
            where TSchema : Toolkit.Services.SchemaBase
        {
            try
            {
                var uri = new Uri($"{BaseUrl}/statuses/home_timeline.json?count={maxRecords}");

                TwitterOAuthRequest request = new TwitterOAuthRequest();
                var rawResult = await request.ExecuteGetAsync(uri, _tokens);

                return(parser.Parse(rawResult));
            }
            catch (WebException wex)
            {
                HttpWebResponse response = wex.Response as HttpWebResponse;
                if (response != null)
                {
                    if ((int)response.StatusCode == 429)
                    {
                        throw new TooManyRequestsException();
                    }

                    if (response.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        throw new OAuthKeysRevokedException();
                    }
                }

                throw;
            }
        }
        /// <summary>
        /// Search for specific hash tag with specific parser.
        /// </summary>
        /// <typeparam name="TSchema">Strong type for results.</typeparam>
        /// <param name="hashTag">Hash tag.</param>
        /// <param name="maxRecords">Upper record limit.</param>
        /// <param name="parser">Specific results parser.</param>
        /// <returns>Returns strongly typed list of results.</returns>
        public async Task <IEnumerable <TSchema> > SearchAsync <TSchema>(string hashTag, int maxRecords, Toolkit.Services.IParser <TSchema> parser)
            where TSchema : Toolkit.Services.SchemaBase
        {
            try
            {
                var uri = new Uri($"{BaseUrl}/search/tweets.json?q={Uri.EscapeDataString(hashTag)}&count={maxRecords}");
                TwitterOAuthRequest request = new TwitterOAuthRequest();
                var rawResult = await request.ExecuteGetAsync(uri, _tokens);

                var result = parser.Parse(rawResult);
                return(result
                       .Take(maxRecords)
                       .ToList());
            }
            catch (WebException wex)
            {
                HttpWebResponse response = wex.Response as HttpWebResponse;
                if (response != null)
                {
                    if ((int)response.StatusCode == 429)
                    {
                        throw new TooManyRequestsException();
                    }

                    if (response.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        throw new OAuthKeysRevokedException();
                    }
                }

                throw;
            }
        }
        /// <summary>
        /// Wrapper around REST API for making data request.
        /// </summary>
        /// <typeparam name="TSchema">Schema to use</typeparam>
        /// <param name="config">Query configuration.</param>
        /// <param name="maxRecords">Upper limit for records returned.</param>
        /// <param name="pageIndex">The zero-based index of the page that corresponds to the items to retrieve.</param>
        /// <param name="parser">IParser implementation for interpreting results.</param>
        /// <returns>Strongly typed list of results.</returns>
        protected override async Task <IEnumerable <TSchema> > GetDataAsync <TSchema>(TwitterDataConfig config, int maxRecords, int pageIndex, Toolkit.Services.IParser <TSchema> parser)
        {
            IEnumerable <TSchema> items;

            switch (config.QueryType)
            {
            case TwitterQueryType.User:
                items = await GetUserTimeLineAsync(config.Query, maxRecords, parser);

                break;

            case TwitterQueryType.Search:
                items = await SearchAsync(config.Query, maxRecords, parser);

                break;

            case TwitterQueryType.Home:
            case TwitterQueryType.Custom:
                items = await GetCustomSearch(config.Query, parser);

                break;

            default:
                items = await GetHomeTimeLineAsync(maxRecords, parser);

                break;
            }

            return(items);
        }
        /// <summary>
        /// Retrieve user timeline data with specific parser.
        /// </summary>
        /// <typeparam name="TSchema">Strong type for results.</typeparam>
        /// <param name="screenName">User screen name.</param>
        /// <param name="maxRecords">Upper record limit.</param>
        /// <param name="parser">Specific results parser.</param>
        /// <returns>Returns strongly typed list of results.</returns>
        public async Task <IEnumerable <TSchema> > GetUserTimeLineAsync <TSchema>(string screenName, int maxRecords, Toolkit.Services.IParser <TSchema> parser)
            where TSchema : Toolkit.Services.SchemaBase
        {
            string rawResult = null;

            try
            {
                var uri = new Uri($"{BaseUrl}/statuses/user_timeline.json?screen_name={screenName}&count={maxRecords}&include_rts=1");

                TwitterOAuthRequest request = new TwitterOAuthRequest();
                rawResult = await request.ExecuteGetAsync(uri, _tokens);

                var result = parser.Parse(rawResult);
                return(result
                       .Take(maxRecords)
                       .ToList());
            }
            catch (WebException wex)
            {
                HttpWebResponse response = wex.Response as HttpWebResponse;
                if (response != null)
                {
                    if (response.StatusCode == HttpStatusCode.NotFound)
                    {
                        throw new UserNotFoundException(screenName);
                    }

                    if ((int)response.StatusCode == 429)
                    {
                        throw new TooManyRequestsException();
                    }

                    if (response.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        throw new OAuthKeysRevokedException();
                    }
                }

                throw;
            }
            catch
            {
                if (!string.IsNullOrEmpty(rawResult))
                {
                    var errors = JsonConvert.DeserializeObject <TwitterErrors>(rawResult);

                    throw new TwitterException {
                              Errors = errors
                    };
                }

                throw;
            }
        }