package cz.muni.fi.lasaris.sbms.data.providers;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import cz.muni.fi.lasaris.sbms.data.entities.Address;
import cz.muni.fi.lasaris.sbms.data.entities.AggregationFunction;
import cz.muni.fi.lasaris.sbms.data.entities.Interpolation;
import cz.muni.fi.lasaris.sbms.data.entities.SeriesSpecs;
import cz.muni.fi.lasaris.sbms.data.entities.containers.Series;
import cz.muni.fi.lasaris.sbms.data.entities.containers.Slice;
import cz.muni.fi.lasaris.sbms.data.entities.containers.Trend;
import cz.muni.fi.lasaris.sbms.data.entities.containers.TrendGroup;
import cz.muni.fi.lasaris.sbms.data.entities.values.AggregatedValue;
import cz.muni.fi.lasaris.sbms.data.entities.values.InterpolatedValue;

public interface TrendsProvider {
		
		public void init(Properties props, String name, String propertiesPrefix);
		
		public void close();
	
		/**
		 * returns time series - either with interpolation or raw data
		 * @param trend
		 * @param s
		 * @return
		 */
		public Trend getTrend(Address trend, SeriesSpecs s);
		
		/**
		 *  complete trend data for multiple trends - used for custom aggregation or direct inspection 
		 * @param trends
		 * @param s
		 * @return
		 */
		public TrendGroup getTrends(List<Address> trends, SeriesSpecs s);
		
		/**
		 *  trend data provided in groups - used for custom aggregations
		 * @param trends
		 * @param s
		 * @return
		 */
		public Map<String, TrendGroup> getTrendsByGroup(Map<String, List<Address>> trendGroups, SeriesSpecs s);
		
		/**
		 *  returns aggregated value for given trend
		 * @param trendGroups
		 * @param seriesSpecs
		 * @param aggregation
		 * @return
		 */
		public AggregatedValue getTrendAggregation(Address trend, SeriesSpecs seriesSpecs, AggregationFunction aggregation);
		
		/**
		 *  returns aggregated values for each of the trends
		 * @param trends
		 * @param seriesSpecs
		 * @param aggregation
		 * @return
		 */
		public Map<Address, AggregatedValue> getTrendAggregations(List<Address> trends, SeriesSpecs seriesSpecs, AggregationFunction aggregation);
		
		/**
		 * Computes one aggregated value for multiple trends. In the first step, it computes aggregation for each trend separately.
		 * In the second step, the aggregated values are aggregated once more using the same method.
		 * In case of weighted AVG and weighted temporal AVG, in the first step, classic AVG/temporal AVG is computed. In the second step, weights
		 * are added to the classic AVG computation.
		 * @param trends
		 * @param seriesSpecs
		 * @param aggregation
		 * @return
		 */
		public AggregatedValue getTrendsAggregation(List<Address> trends, SeriesSpecs seriesSpecs, AggregationFunction aggregation);
		
		/**
		 *  aggregations over time and groups
		 * @param trends
		 * @param seriesSpecs
		 * @param aggregation
		 * @return
		 */
		public Map<String, AggregatedValue> getGroupTrendAggregations(Map<String, List<Address>> trendGroups, SeriesSpecs seriesSpecs, AggregationFunction aggregation);
		
		/**
		 *  methods that might perform some sort of interpolation - return one value for one moment in time
		 * @param trendGroups
		 * @param timestamp
		 * @param interpolation
		 * @return
		 */
		public InterpolatedValue getTrendValue(Address trend, ZonedDateTime timestamp, Interpolation interpolation);
		
		/**
		 *  returns slice - for each address one value at give time (interpolation will likely occur)
		 * @param trends
		 * @param timestamp
		 * @param interpolation
		 * @return
		 */
		public Slice getSlice(List<Address> trends, ZonedDateTime timestamp, Interpolation interpolation);
		
		/**
		 *  returns "slices" - values of trends in given time (equivalent to repeated call to getTrendValues with different timestamps)
		 * @param trends
		 * @param seriesSpecs
		 * @return
		 */
		public Series<Slice> getSlices(List<Address> trends, SeriesSpecs seriesSpecs);
		
		/**
		 *  creates aggregation over "slices" - performs aggregation on the slice, not on the individual trend
		 * @param trends
		 * @param seriesSpecs
		 * @param aggregation
		 * @return
		 */
		public Series<AggregatedValue> getSliceAggregations(List<Address> trends, SeriesSpecs seriesSpecs, AggregationFunction aggregation);
		
		/**
		 *  aggregations over slice and group
		 * @param trendGroups
		 * @param seriesSpecs
		 * @param aggregation
		 * @return
		 */
		public Series<Map<String, AggregatedValue>> getGroupSliceAggregations(Map<String, List<Address>> trendGroups, SeriesSpecs seriesSpecs, AggregationFunction aggregation);
		
}
