// Path: src/main/java/com/statful/client/Aggregation.java
// public enum Aggregation {
//     /**
//      * Average aggregation
//      */
//     AVG("avg"),
//     /**
//      * Percentile 90 aggregation
//      */
//     P90("p90"),
//     /**
//      * Count aggregation
//      */
//     COUNT("count"),
//     /**
//      * Last aggregation
//      */
//     LAST("last"),
//     /**
//      * Summatory aggregation
//      */
//     SUM("sum"),
//     /**
//      * First aggregation
//      */
//     FIRST("first"),
//     /**
//      * Percentile 95 aggregation
//      */
//     P95("p95"),
//     /**
//      * Percentile 99 aggregation
//      */
//     P99("p99"),
//     /**
//      * Aggregate by min value
//      */
//     MIN("min"),
//     /**
//      * Aggregate by max value
//      */
//     MAX("max");
// 
//     /**
//      * String representation of the aggregation
//      */
//     private final String name;
// 
//     /**
//      * private constructor to force that all entries have a name
//      *
//      * @param name String representation of the aggregation
//      */
//     Aggregation(final String name) {
//         this.name = name;
//     }
// 
//     /**
//      * Gets the string value of the aggregation, to be used to build metric lines
//      *
//      * @return String with the aggregation representation
//      */
//     public final String getName() {
//         return name;
//     }
// }
// 
// Path: src/main/java/com/statful/client/AggregationFreq.java
// public enum AggregationFreq {
// 
//     /**
//      * 10 seconds aggregation
//      */
//     FREQ_10("10"),
// 
//     /**
//      * 30 seconds aggregation
//      */
//     FREQ_30("30"),
// 
//     /**
//      * 60 seconds aggregation
//      */
//     FREQ_60("60"),
// 
//     /**
//      * 120 seconds aggregation
//      */
//     FREQ_120("120"),
// 
//     /**
//      * 180 seconds aggregation
//      */
//     FREQ_180("180"),
// 
//     /**
//      * 300 seconds aggregation
//      */
//     FREQ_300("300");
// 
//     /**
//      * Number of seconds desired for the aggregation
//      */
//     private String value;
// 
// 
//     /**
//      * private constructor to force that all entries have a frequency string representation
//      *
//      * @param value String representation of the frequency
//      */
//     AggregationFreq(final String value) {
//         this.value = value;
//     }
// 
//     /**
//      * Gets the string value of the frequency, to be used to build metric lines
//      *
//      * @return String with the frequency representation
//      */
//     public String getValue() {
//         return this.value;
//     }
// }
// 
// Path: src/main/java/com/statful/client/MetricType.java
// public enum MetricType {
//     /**
//      * Type for gauge metrics
//      */
//     GAUGE("gauge"),
//     /**
//      * Type for counter metrics
//      */
//     COUNTER("counter"),
//     /**
//      * Type for timer metrics
//      */
//     TIMER("timer");
// 
//     /**
//      * String representation of this metric type
//      */
//     private String value;
// 
//     MetricType(final String value) {
//         this.value = value;
//     }
// 
//     /**
//      * Returns the default aggregation list for this metric type.
//      *
//      * @param statfulMetricsOptions Configured statful client metric options
//      * @return List of {@link Aggregation}
//      */
//     public List<Aggregation> getDefaultAggregationFromOptions(final StatfulMetricsOptions statfulMetricsOptions) {
//         switch (this) {
//             case GAUGE:
//                 return statfulMetricsOptions.getGaugeAggregations();
//             case COUNTER:
//                 return statfulMetricsOptions.getCounterAggregations();
//             case TIMER:
//                 return statfulMetricsOptions.getTimerAggregations();
//             default:
//                 throw new IllegalArgumentException("Invalid metric type.");
//         }
//     }
// 
//     /**
//      * Returns the default aggregation frequency for this metric type.
//      *
//      * @param statfulMetricsOptions Configured statful client metric options
//      * @return An {@link AggregationFreq}
//      */
//     public AggregationFreq getDefaultAggregationFrequencyFromOptions(final StatfulMetricsOptions statfulMetricsOptions) {
//         switch (this) {
//             case GAUGE:
//                 return statfulMetricsOptions.getGaugeFrequency();
//             case COUNTER:
//                 return statfulMetricsOptions.getCounterFrequency();
//             case TIMER:
//                 return statfulMetricsOptions.getTimerFrequency();
//             default:
//                 throw new IllegalArgumentException("Invalid metric type.");
//         }
//     }
// 
//     @Override
//     public String toString() {
//         return this.value;
//     }
// }


import com.google.common.base.Strings;
import com.statful.client.Aggregation;
import com.statful.client.AggregationFreq;
import com.statful.client.MetricType;
import javax.annotation.Nonnull;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.Objects.isNull;
package com.statful.metric;




/**
 * Statful metric line builder. Builds metrics lines according to Statful specification
 */
public final class MetricLineBuilder {

    /**
     * Optional application name to be added to the tag list
     */
    private String app;

    /**
     * Namespace to be set in the metric
     */
    private String namespace;

    /**
     * Optional metric type to be set in the metric
     */
    private MetricType metricType;

    /**
     * Metric name to be added to the metric
     */
    private String metricName;

    /**
     * Tags to be applied in the metric
     */
    private Map<String, String> tags;

    /**
     * Metric value to be sent
     */
    private String value;

    /**
     * Timestamp of when the metric was collected
     */
    private long timestamp;

    /**
     * List of aggregations to be applied to the sent metric
     */
    private List<Aggregation> aggregations = new ArrayList<>();

    /**
     * Frequency of aggregation to be applied to the metric
     */
// Path: src/main/java/com/statful/client/Aggregation.java
// public enum Aggregation {
//     /**
//      * Average aggregation
//      */
//     AVG("avg"),
//     /**
//      * Percentile 90 aggregation
//      */
//     P90("p90"),
//     /**
//      * Count aggregation
//      */
//     COUNT("count"),
//     /**
//      * Last aggregation
//      */
//     LAST("last"),
//     /**
//      * Summatory aggregation
//      */
//     SUM("sum"),
//     /**
//      * First aggregation
//      */
//     FIRST("first"),
//     /**
//      * Percentile 95 aggregation
//      */
//     P95("p95"),
//     /**
//      * Percentile 99 aggregation
//      */
//     P99("p99"),
//     /**
//      * Aggregate by min value
//      */
//     MIN("min"),
//     /**
//      * Aggregate by max value
//      */
//     MAX("max");
// 
//     /**
//      * String representation of the aggregation
//      */
//     private final String name;
// 
//     /**
//      * private constructor to force that all entries have a name
//      *
//      * @param name String representation of the aggregation
//      */
//     Aggregation(final String name) {
//         this.name = name;
//     }
// 
//     /**
//      * Gets the string value of the aggregation, to be used to build metric lines
//      *
//      * @return String with the aggregation representation
//      */
//     public final String getName() {
//         return name;
//     }
// }
// 
// Path: src/main/java/com/statful/client/AggregationFreq.java
// public enum AggregationFreq {
// 
//     /**
//      * 10 seconds aggregation
//      */
//     FREQ_10("10"),
// 
//     /**
//      * 30 seconds aggregation
//      */
//     FREQ_30("30"),
// 
//     /**
//      * 60 seconds aggregation
//      */
//     FREQ_60("60"),
// 
//     /**
//      * 120 seconds aggregation
//      */
//     FREQ_120("120"),
// 
//     /**
//      * 180 seconds aggregation
//      */
//     FREQ_180("180"),
// 
//     /**
//      * 300 seconds aggregation
//      */
//     FREQ_300("300");
// 
//     /**
//      * Number of seconds desired for the aggregation
//      */
//     private String value;
// 
// 
//     /**
//      * private constructor to force that all entries have a frequency string representation
//      *
//      * @param value String representation of the frequency
//      */
//     AggregationFreq(final String value) {
//         this.value = value;
//     }
// 
//     /**
//      * Gets the string value of the frequency, to be used to build metric lines
//      *
//      * @return String with the frequency representation
//      */
//     public String getValue() {
//         return this.value;
//     }
// }
// 
// Path: src/main/java/com/statful/client/MetricType.java
// public enum MetricType {
//     /**
//      * Type for gauge metrics
//      */
//     GAUGE("gauge"),
//     /**
//      * Type for counter metrics
//      */
//     COUNTER("counter"),
//     /**
//      * Type for timer metrics
//      */
//     TIMER("timer");
// 
//     /**
//      * String representation of this metric type
//      */
//     private String value;
// 
//     MetricType(final String value) {
//         this.value = value;
//     }
// 
//     /**
//      * Returns the default aggregation list for this metric type.
//      *
//      * @param statfulMetricsOptions Configured statful client metric options
//      * @return List of {@link Aggregation}
//      */
//     public List<Aggregation> getDefaultAggregationFromOptions(final StatfulMetricsOptions statfulMetricsOptions) {
//         switch (this) {
//             case GAUGE:
//                 return statfulMetricsOptions.getGaugeAggregations();
//             case COUNTER:
//                 return statfulMetricsOptions.getCounterAggregations();
//             case TIMER:
//                 return statfulMetricsOptions.getTimerAggregations();
//             default:
//                 throw new IllegalArgumentException("Invalid metric type.");
//         }
//     }
// 
//     /**
//      * Returns the default aggregation frequency for this metric type.
//      *
//      * @param statfulMetricsOptions Configured statful client metric options
//      * @return An {@link AggregationFreq}
//      */
//     public AggregationFreq getDefaultAggregationFrequencyFromOptions(final StatfulMetricsOptions statfulMetricsOptions) {
//         switch (this) {
//             case GAUGE:
//                 return statfulMetricsOptions.getGaugeFrequency();
//             case COUNTER:
//                 return statfulMetricsOptions.getCounterFrequency();
//             case TIMER:
//                 return statfulMetricsOptions.getTimerFrequency();
//             default:
//                 throw new IllegalArgumentException("Invalid metric type.");
//         }
//     }
// 
//     @Override
//     public String toString() {
//         return this.value;
//     }
// }


// Path: src/main/java/com/statful/metric/MetricLineBuilder.java
import com.google.common.base.Strings;
import com.statful.client.Aggregation;
import com.statful.client.AggregationFreq;
import com.statful.client.MetricType;
import javax.annotation.Nonnull;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.Objects.isNull;

package com.statful.metric;




/**
 * Statful metric line builder. Builds metrics lines according to Statful specification
 */
public final class MetricLineBuilder {

    /**
     * Optional application name to be added to the tag list
     */
    private String app;

    /**
     * Namespace to be set in the metric
     */
    private String namespace;

    /**
     * Optional metric type to be set in the metric
     */
    private MetricType metricType;

    /**
     * Metric name to be added to the metric
     */
    private String metricName;

    /**
     * Tags to be applied in the metric
     */
    private Map<String, String> tags;

    /**
     * Metric value to be sent
     */
    private String value;

    /**
     * Timestamp of when the metric was collected
     */
    private long timestamp;

    /**
     * List of aggregations to be applied to the sent metric
     */
    private List<Aggregation> aggregations = new ArrayList<>();

    /**
     * Frequency of aggregation to be applied to the metric
     */
    private AggregationFreq frequency = AggregationFreq.FREQ_10;