/// <summary>
        /// Deserializes the specified stream.
        /// </summary>
        /// <param name="stream">The stream to deserialize.</param>
        /// <param name="definitions">The time series definitions.</param>
        /// <param name="numSamplingTypesRequested">The number of requested sampling types. OBO needs to specify this since it doesn't know the <paramref name="definitions"/>.</param>
        /// <returns>
        /// Item1 of the tuple is the list of metric names, and Item2 is the time series values.
        /// When <paramref name="definitions" /> is null (OBO case), each time series object contains only the error code and the metric values queryable via sampling type indexes.
        /// </returns>
        public static Tuple <string[], TimeSeries <MetricIdentifier, double?>[]> Deserialize(
            Stream stream,
            IReadOnlyList <TimeSeriesDefinition <MetricIdentifier> > definitions,
            int numSamplingTypesRequested = -1)
        {
            if (definitions == null && numSamplingTypesRequested <= 0)
            {
                throw new ArgumentException($"{numSamplingTypesRequested} must be > 0 when {nameof(definitions)} is null.");
            }

            using (var reader = new BinaryReader(stream))
            {
                var version = reader.ReadByte();

                if (version > NextVersion)
                {
                    throw new MetricsClientException($"The server didn't respond with the right version of serialization. CurrentVersion : {CurrentVersion}, NextVersion : {NextVersion}, Responded: {version}.");
                }

                // Get the number of metric names required for OBO scenario since OBO service doesn't know the metrics to query,
                // and it is MdmRP that fills them in.
                var numMetricNames = reader.ReadInt16();

                string[] metricNames;
                if (numMetricNames == 0)
                {
                    metricNames = null;
                }
                else
                {
                    metricNames = new string[(int)numMetricNames];
                    for (int i = 0; i < numMetricNames; ++i)
                    {
                        metricNames[i] = reader.ReadString();
                    }
                }

                var numSeries = SerializationUtils.ReadUInt32FromBase128(reader);

                TimeSeries <MetricIdentifier, double?>[] seriesArray = null;

                seriesArray = new TimeSeries <MetricIdentifier, double?> [(int)numSeries];

                for (int i = 0; i < numSeries; i++)
                {
                    var deserialized = DeserializeOneSeries(version, reader, definitions?[i], numSamplingTypesRequested);
                    if (definitions == null)
                    {
                        seriesArray[i] = new TimeSeries <MetricIdentifier, double?>(DefaultDateTime, DefaultDateTime, 1, null, deserialized.Values, deserialized.ErrorCode);
                    }
                    else
                    {
                        var definition = definitions[i];
                        if (deserialized.Values != null)
                        {
                            var startTime = definition.StartTimeUtc.AddMinutes(deserialized.DeltaOfStartTimeInMinutes);

                            var resolutionWindow = definition.SeriesResolutionInMinutes + deserialized.DeltaOfSeriesResolutionInMinutes;

                            var endTimeUtc = startTime + TimeSpan.FromMinutes(resolutionWindow * (deserialized.Values[0].Count - 1));

                            seriesArray[i] = new TimeSeries <MetricIdentifier, double?>(startTime, endTimeUtc, resolutionWindow, definition, deserialized.Values, deserialized.ErrorCode);
                        }
                        else
                        {
                            seriesArray[i] = new TimeSeries <MetricIdentifier, double?>(definition.StartTimeUtc, definition.EndTimeUtc, definition.SeriesResolutionInMinutes, definition, deserialized.Values, deserialized.ErrorCode);
                        }
                    }
                }

                return(Tuple.Create(metricNames, seriesArray));
            }
        }
        /// <summary>
        /// Gets a list of the time series, each with multiple sampling types.
        /// </summary>
        /// <param name="startTimeUtc">The start time UTC.</param>
        /// <param name="endTimeUtc">The end time UTC.</param>
        /// <param name="samplingTypes">The sampling types.</param>
        /// <param name="definitions">The time series definitions.</param>
        /// <param name="seriesResolutionInMinutes">The resolution window used to reduce the resolution of the returned series.</param>
        /// <param name="aggregationType">The aggregation function used to reduce the resolution of the returned series.</param>
        /// <returns>The time series of for the given definitions.</returns>
        public Task <IEnumerable <TimeSeries <MetricIdentifier, double?> > > GetMultipleTimeSeriesAsync(DateTime startTimeUtc, DateTime endTimeUtc, SamplingType[] samplingTypes, IEnumerable <TimeSeriesDefinition <MetricIdentifier> > definitions, int seriesResolutionInMinutes = 1, AggregationType aggregationType = AggregationType.Automatic)
        {
            IEnumerable <TimeSeries <MetricIdentifier, double?> > series = new TimeSeries <MetricIdentifier, double?>[] { };

            return(Task.FromResult(series));
        }