/**
 * Copyright 2017 Pivotal Software, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.metrics.instrument.prometheus;

import com.google.common.collect.Streams;
import io.prometheus.client.Collector;
import org.springframework.metrics.instrument.Tag;
import org.springframework.metrics.instrument.stats.Quantiles;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.DoubleAdder;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * Necessitated by a desire to offer different quantile algorithms.
 *
 * @author Jon Schneider
 */
public class CustomPrometheusSummary extends Collector {
    private final String name;
    private final String countName;
    private final String sumName;
    private final List<String> tagKeys;

    private final Collection<Child> children = new ConcurrentLinkedQueue<>();

    CustomPrometheusSummary(String name, Iterable<Tag> tags) {
        this.name = name;
        this.countName = name + "_count";
        this.sumName = name + "_sum";
        this.tagKeys = Streams.stream(tags).map(Tag::getKey).collect(toList());
    }

    public Child child(Iterable<Tag> tags, Quantiles quantiles) {
        Child child = new Child(tags, quantiles);
        children.add(child);
        return child;
    }

    class Child {
        private final List<String> tagValues;
        private final Quantiles quantiles;
        private List<String> quantileKeys;

        private LongAdder count = new LongAdder();
        private DoubleAdder sum = new DoubleAdder();

        Child(Iterable<Tag> tags, Quantiles quantiles) {
            this.quantiles = quantiles;
            this.tagValues = Streams.stream(tags).map(Tag::getValue).collect(toList());

            if(quantiles != null) {
                quantileKeys = new LinkedList<>(tagKeys);
                quantileKeys.add("quantile");
            }
        }

        public Stream<MetricFamilySamples.Sample> collect() {
            Stream.Builder<MetricFamilySamples.Sample> samples = Stream.builder();

            if(quantiles != null) {
                for(Double q: quantiles.monitored()) {
                    List<String> quantileValues = new LinkedList<>(tagValues);
                    quantileValues.add(Collector.doubleToGoString(q));
                    samples.add(new MetricFamilySamples.Sample(name, quantileKeys, quantileValues, quantiles.get(q)));
                }
            }

            samples.add(new MetricFamilySamples.Sample(countName, tagKeys, tagValues, count.sum()));
            samples.add(new MetricFamilySamples.Sample(sumName, tagKeys, tagValues, sum.sum()));

            return samples.build();
        }

        public void observe(double amt) {
            count.add(1);
            sum.add(amt);
            if (quantiles != null) {
                quantiles.observe(amt);
            }
        }

        public long count() {
            return count.sum();
        }

        public double sum() {
            return sum.sum();
        }
    }

    @Override
    public List<MetricFamilySamples> collect() {
        return Collections.singletonList(new MetricFamilySamples(name, Type.SUMMARY, "", children.stream()
            .flatMap(Child::collect).collect(toList())));
    }
}

@@ -664,50 +664,8 @@
 s;%0A%0A
-import com.google.common.collect.Streams;%0A
 impo
@@ -831,17 +831,26 @@
 va.util.
-*
+Collection
 ;%0Aimport
@@ -864,87 +864,48 @@
 til.
-concurrent.ConcurrentHashMap;%0Aimport java.util.concurrent.Concurrent
+Collections;%0Aimport java.util.
 Linked
-Queue
+List
 ;%0Aim
@@ -923,32 +923,12 @@
 til.
-concurrent.ConcurrentMap
+List
 ;%0Aim
@@ -967,19 +967,19 @@
 rent
-SkipListSet
+LinkedQueue
 ;%0Aim
@@ -1074,44 +1074,8 @@
 er;%0A
-import java.util.stream.Collectors;%0A
 impo
@@ -1152,16 +1152,69 @@
 .toList;
+%0Aimport static java.util.stream.StreamSupport.stream;
 %0A%0A/**%0A *
@@ -1777,32 +1777,24 @@
 s.tagKeys = 
-Streams.
 stream(tags)
@@ -1784,32 +1784,53 @@
 ys = stream(tags
+.spliterator(), false
 ).map(Tag::getKe
@@ -2418,16 +2418,8 @@
 s = 
-Streams.
 stre
@@ -2425,16 +2425,37 @@
 eam(tags
+.spliterator(), false
 ).map(Ta

Remove dependency on Guava in CustomPrometheusSummary