/// <summary>
        /// Get a list of Historics queries in your account.
        /// </summary>
        /// <param name="user">The user making the request.</param>
        /// <param name="page">The page number to get.</param>
        /// <param name="per_page">The number of items per page.</param>
        /// <returns>A list of Historic objects.</returns>
        public static HistoricList list(User user, int page = 1, int per_page = 20)
        {
            try
            {
                Dictionary <string, string> parameters = new Dictionary <string, string>();
                parameters.Add("page", page.ToString());
                parameters.Add("per_page", per_page.ToString());
                JSONdn res = user.callApi("historics/get", parameters);

                if (!res.has("count"))
                {
                    throw new ApiException("No count in the response");
                }
                HistoricList retval = new HistoricList(res.getIntVal("count"));

                if (!res.has("data") && retval.TotalCount > 0)
                {
                    throw new ApiException("No historics in the response");
                }
                JToken[] children = res.getChildren("data");
                for (int i = 0; i < children.Length; i++)
                {
                    retval.Add(new Historic(user, new JSONdn(children[i])));
                }
                return(retval);
            }
            catch (ApiException e)
            {
                if (e.Code == 400)
                {
                    throw new InvalidDataException(e.Message);
                }
                throw new ApiException("Unexpected API response code: " + e.Code.ToString() + " " + e.Message);
            }
        }
        /// <summary>
        /// Page through recent Push log entries.
        /// </summary>
        /// <param name="user">The user making the request.</param>
        /// <param name="page">Which page to fetch.</param>
        /// <param name="per_page">How many entries per page.</param>
        /// <param name="order_by">Which field to sort by.</param>
        /// <param name="order_dir">In asc[ending] or desc[ending] order.</param>
        /// <param name="id">Optional subscription ID.</param>
        /// <returns>A PushLog object.</returns>
        public static PushLog getLogs(User user, int page, int per_page, string order_by = ORDERBY_REQUEST_TIME, string order_dir = ORDERDIR_DESC, string id = "")
        {
            Dictionary <string, string> parameters = new Dictionary <string, string>();

            if (page < 1)
            {
                throw new InvalidDataException("The specified page number is invalid");
            }

            if (per_page < 1)
            {
                throw new InvalidDataException("The specified per_page value is invalid");
            }

            if (order_by != ORDERBY_REQUEST_TIME)
            {
                throw new InvalidDataException("The specified order_by is not supported");
            }

            if (order_dir != ORDERDIR_ASC && order_dir != ORDERDIR_DESC)
            {
                throw new InvalidDataException("The specified order_dir is not supported");
            }

            if (id.Length > 0)
            {
                parameters.Add("id", id);
            }

            parameters.Add("page", page.ToString());
            parameters.Add("per_page", per_page.ToString());
            parameters.Add("order_by", order_by);
            parameters.Add("order_dir", order_dir);

            JSONdn res = user.callApi("push/log", parameters);

            if (!res.has("count"))
            {
                throw new ApiException("No count in the response");
            }
            PushLog retval = new PushLog(res.getIntVal("count"));

            if (!res.has("log_entries") && retval.TotalCount > 0)
            {
                throw new ApiException("No log entries in the response");
            }
            JToken[] children = res.getChildren("log_entries");
            for (int i = 0; i < children.Length; i++)
            {
                retval.Add(new PushLogEntry(new JSONdn(children[i])));
            }
            return(retval);
        }
        /// <summary>
        /// Get buffered tweets.
        /// </summary>
        /// <param name="count">The number of tweets to get - see http://dev.datasift.com/ for the limit.</param>
        /// <param name="from_id">The ID of the latest interaction that you received.</param>
        /// <returns>An array of Interaction objects.</returns>
        public Interaction[] getBuffered(uint count = 0, ulong from_id = 0)
        {
            if (m_csdl.Length == 0)
            {
                throw new InvalidDataException("Cannot get buffered interactions for an empty definition");
            }

            Dictionary <string, string> parameters = new Dictionary <string, string>();

            parameters.Add("hash", getHash());
            if (count > 0)
            {
                parameters.Add("count", count.ToString());
            }
            if (from_id > 0)
            {
                parameters.Add("from_id", from_id.ToString());
            }

            JSONdn res = m_user.callApi("stream", parameters);

            if (!res.has("stream"))
            {
                throw new ApiException("No data in the response", -1);
            }

            List <Interaction> retval = new List <Interaction>();

            JToken[] children = res.getChildren("stream");
            for (int i = 0; i < children.Length; i++)
            {
                retval.Add(new Interaction(children[i]));
            }

            return(retval.ToArray());
        }
        /// <summary>
        /// Get a page of Push subscriptions in the given user's account,
        /// where each page contains up to per_page items. Results will be
        /// ordered according to the supplied ordering parameters.
        /// </summary>
        /// <param name="user">The user object making the request.</param>
        /// <param name="page">The page number to get.</param>
        /// <param name="per_page">The number of items per page.</param>
        /// <param name="order_by">The field by which to order the results.</param>
        /// <param name="order_dir">Ascending or descending.</param>
        /// <param name="include_finished">True to include subscriptions against finished Historics queries.</param>
        /// <param name="hash_type">Optional hash type to look for (hash is also required)</param>
        /// <param name="hash">Optional hash to look for (hash_type is also required)</param>
        /// <returns>A PushSubscriptionList object.</returns>
        public static PushSubscriptionList list(User user, int page, int per_page, string order_by = ORDERBY_CREATED_AT, string order_dir = ORDERDIR_ASC, bool include_finished = false, string hash_type = "", string hash = "")
        {
            Dictionary <string, string> parameters = new Dictionary <string, string>();

            if (hash_type.Length > 0)
            {
                if (hash_type != "hash" && hash_type != "playback_id")
                {
                    throw new InvalidDataException("Hash type is invalid");
                }
                if (hash.Length == 0)
                {
                    throw new InvalidDataException("Hash type given but the hash is empty");
                }
                parameters.Add(hash_type, hash);
            }

            if (page < 1)
            {
                throw new InvalidDataException("The specified page number is invalid");
            }

            if (per_page < 1)
            {
                throw new InvalidDataException("The specified per_page value is invalid");
            }

            if (order_by != ORDERBY_ID && order_by != ORDERBY_CREATED_AT)
            {
                throw new InvalidDataException("The specified order_by is not supported");
            }

            if (order_dir != ORDERDIR_ASC && order_dir != ORDERDIR_DESC)
            {
                throw new InvalidDataException("The specified order_dir is not supported");
            }

            parameters.Add("page", page.ToString());
            parameters.Add("per_page", per_page.ToString());
            parameters.Add("order_by", order_by);
            parameters.Add("order_dir", order_dir);

            if (include_finished)
            {
                parameters.Add("include_finished", "1");
            }

            JSONdn res = user.callApi("push/get", parameters);

            if (!res.has("count"))
            {
                throw new ApiException("No count in the response");
            }
            PushSubscriptionList retval = new PushSubscriptionList(res.getIntVal("count"));

            if (!res.has("subscriptions") && retval.TotalCount > 0)
            {
                throw new ApiException("No subscriptions in the response");
            }
            JToken[] children = res.getChildren("subscriptions");
            for (int i = 0; i < children.Length; i++)
            {
                retval.Add(new PushSubscription(user, new JSONdn(children[i])));
            }
            return(retval);
        }