package com.custardsource.parfait;

import java.util.List;

import javax.measure.unit.Unit;

import net.jcip.annotations.NotThreadSafe;

import com.google.common.base.Supplier;
import com.google.common.collect.Lists;

@NotThreadSafe
public class PeriodicValueBuilder {
	private final List<Period> periods = Lists.newArrayList();
	private final Supplier<Long> timeSource;
	private final MonitorableRegistry registry;

	public PeriodicValueBuilder(MonitorableRegistry registry) {
		this(PeriodicValue.SYSTEM_TIME_SOURCE, registry);
	}

	PeriodicValueBuilder(Supplier<Long> timeSource, MonitorableRegistry registry) {
		this.registry = registry;
		this.timeSource = timeSource;
	}

	public void addPeriod(Period period) {
		periods.add(period);
	}

	public CompositeCounter build(String baseName, String baseDescription, Unit<?> unit) {
		List<Counter> values = Lists.newArrayList();
		for (Period period : periods) {
			final PeriodicValue value = new PeriodicValue(period.getResolution(), period.getPeriod(),
					timeSource);
			
			new PollingMonitoredValue<Long>(baseName + "."
					+ period.getName(), baseDescription + " [" + period.getName()
					+ "]", registry, period.getResolution(), new Poller<Long>() {
				@Override
				public Long poll() {
					return value.get();
				}
			}, ValueSemantics.FREE_RUNNING, unit);
			
			values.add(value);
		}
		return new CompositeCounter(values);
	}
	
	public CompositeCounter copyFrom(Monitorable<?> templateMonitorable) {
		return build(templateMonitorable.getName(), templateMonitorable.getDescription(),
				templateMonitorable.getUnit());
	}
	
	public static final class Period {
		private final int resolution;
		private final long period;
		private final String name;
		
		private Period(int resolution, long period, String name) {
			this.resolution = resolution;
			this.period = period;
			this.name = name;
		}		

		public String getName() {
			return name;
		}

		public int getResolution() {
			return resolution;
		}

		public long getPeriod() {
			return period;
		}
		
		public static Period of(int resolution, long period, String name) {
			return new Period(resolution, period, name);
		}
	}
}
@@ -827,16 +827,231 @@
 unit) %7B%0A
+%09%09List%3CCounter%3E values = getSubCounters(baseName, baseDescription, unit);%0A%09%09return new CompositeCounter(values);%0A%09%7D%0A%0A%09private List%3CCounter%3E getSubCounters(String baseName,%0A%09%09%09String baseDescription, Unit%3C?%3E unit) %7B%0A
 %09%09List%3CC
@@ -1089,16 +1089,16 @@
 List();%0A
-
 %09%09for (P
@@ -1577,36 +1577,14 @@
 urn 
-new CompositeCounter(
 values
-)
 ;%0A%09%7D
@@ -1738,24 +1738,24 @@
 cription(),%0A
-
 %09%09%09%09template
@@ -1776,24 +1776,351 @@
 tUnit());%0A%09%7D
+%0A%0A%09public CompositeCounter wrapCounter(MonitoredCounter templateCounter) %7B%0A%09%09List%3CCounter%3E subCounters = Lists.%3CCounter%3EnewArrayList(templateCounter);%0A%09%09subCounters.addAll(getSubCounters(templateCounter.getName(), templateCounter.getDescription(),%0A%09%09%09%09templateCounter.getUnit()));%0A%09%09return new CompositeCounter(subCounters);%0A%09%7D
 %0A%09%0A%09public s

Allow wrapping an existing MonitoredCounter (surely the most common use case)