/// <summary>
        /// Retrieves a collection of objects based on a set of parameters.
        /// </summary>
        /// <param name="searchOptions">The search options.</param>
        /// <param name="sortOptions">The sort options.</param>
        /// <param name="externs">If you have a relationship between your object and another object, you may want to include the data from a related field in your results. Each external field is listed in the format {object}//{field}.</param>
        /// <param name="listFields">A string array of the fields which should be returned in your results.</param>
        /// <returns>A list of objects matching the query.</returns>
        public async Task <IList <T> > SelectAsync(
            ApiSearchOptions searchOptions = null, ApiSortOptions sortOptions      = null,
            IEnumerable <string> externs   = null, IEnumerable <string> listFields = null)
        {
            var query = new Dictionary <string, object>()
                        .AddSearchOptions(searchOptions)
                        .AddSortOptions(sortOptions)
                        .AddIfHasValue("externs", externs)
                        .AddIfHasValue("listFields", externs);

            var json = await ApiRequest.GetAsync <JObject>(
                $"{EndpointPlural}", query);

            return(await OnParseSelectMultipleAsync(json));
        }
        private async Task <JObject> SelectByTagAsync(ApiObjectType objectType,
                                                      int?tagId = null, string tagName = null,
                                                      ApiSearchOptions searchOptions = null, ApiSortOptions sortOptions      = null,
                                                      IEnumerable <string> externs   = null, IEnumerable <string> listFields = null, bool count = false)
        {
            var query = new Dictionary <string, object>
            {
                { "objectID", (int)objectType },
                { tagId.HasValue ? "tag_id" : "tag_name", (object)tagId ?? tagName },
                { "count", count ? "true" : "false" },
            }
            .AddSearchOptions(searchOptions)
            .AddSortOptions(sortOptions)
            .AddIfHasValue("externs", externs)
            .AddIfHasValue("listFields", listFields);

            return(await _apiRequest.GetAsync <JObject>(
                       "objects/tag", query));
        }
        /// <summary>
        /// Retrieves a collection of objects having a specified tag.
        /// </summary>
        /// <param name="objectType">The object type.</param>
        /// <param name="tagId">The ID of the tag you would like to filter your objects by. Either TagId or TagName is required.</param>
        /// <param name="tagName">The name of the tag you would like to filter your objects by. Either TagId or TagName is required.</param>
        /// <param name="searchOptions">The search options.</param>
        /// <param name="sortOptions">The sort options.</param>
        /// <param name="externs">If you have a relationship between your object and another object, you may want to include the data from a related field in your results. Each external field is listed in the format {object}//{field}.</param>
        /// <param name="listFields">A string array of the fields which should be returned in your results.</param>
        /// <returns>A list of objects matching the query.</returns>
        public async Task <List <Dictionary <string, string> > > SelectByTagAsync(ApiObjectType objectType,
                                                                                  int?tagId = null, string tagName = null,
                                                                                  ApiSearchOptions searchOptions = null, ApiSortOptions sortOptions      = null,
                                                                                  IEnumerable <string> externs   = null, IEnumerable <string> listFields = null)
        {
            var json = await SelectByTagAsync(objectType, tagId, tagName, searchOptions, sortOptions, externs, listFields, false);

            return(json["data"].ToObject <List <Dictionary <string, string> > >());
        }
        /// <summary>
        /// Retrieves the number of objects having a specified tag.
        /// </summary>
        /// <param name="objectType">The object type.</param>
        /// <param name="tagId">The ID of the tag you would like to filter your objects by. Either TagId or TagName is required.</param>
        /// <param name="tagName">The name of the tag you would like to filter your objects by. Either TagId or TagName is required.</param>
        /// <param name="searchOptions">The search options.</param>
        /// <param name="sortOptions">The sort options.</param>
        /// <param name="externs">If you have a relationship between your object and another object, you may want to include the data from a related field in your results. Each external field is listed in the format {object}//{field}.</param>
        /// <param name="listFields">A string array of the fields which should be returned in your results.</param>
        /// <returns>The number of objects matching the query.</returns>
        public async Task <int> GetCountByTagAsync(ApiObjectType objectType,
                                                   int?tagId = null, string tagName = null,
                                                   ApiSearchOptions searchOptions = null, ApiSortOptions sortOptions      = null,
                                                   IEnumerable <string> externs   = null, IEnumerable <string> listFields = null)
        {
            var json = await SelectByTagAsync(objectType, tagId, tagName, searchOptions, sortOptions, externs, listFields, true);

            return(json["data"]["count"].Value <string>().Convert <int>());
        }
        /// <summary>
        /// Retrieves a collection of objects based on a set of parameters.
        /// </summary>
        /// <param name="objectType">The object type.</param>
        /// <param name="searchOptions">The search options.</param>
        /// <param name="sortOptions">The sort options.</param>
        /// <param name="externs">If you have a relationship between your object and another object, you may want to include the data from a related field in your results. Each external field is listed in the format {object}//{field}.</param>
        /// <param name="listFields">A string array of the fields which should be returned in your results.</param>
        /// <returns>A list of objects matching the query.</returns>
        public async Task <List <Dictionary <string, string> > > SelectAsync(ApiObjectType objectType,
                                                                             ApiSearchOptions searchOptions = null, ApiSortOptions sortOptions      = null,
                                                                             IEnumerable <string> externs   = null, IEnumerable <string> listFields = null)
        {
            var query = new Dictionary <string, object>
            {
                { "objectID", (int)objectType }
            }
            .AddSearchOptions(searchOptions)
            .AddSortOptions(sortOptions)
            .AddIfHasValue("externs", externs)
            .AddIfHasValue("listFields", listFields);

            return(await _apiRequest.GetAsync <List <Dictionary <string, string> > >(
                       "objects", query));
        }