/*
 * Copyright 2016 Open Networking Laboratory
 *
 * 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.onosproject.cpman.impl;

import org.apache.commons.lang3.ArrayUtils;
import org.onosproject.cpman.MetricsDatabase;
import org.rrd4j.ConsolFun;
import org.rrd4j.DsType;
import org.rrd4j.core.ArcDef;
import org.rrd4j.core.DsDef;
import org.rrd4j.core.FetchRequest;
import org.rrd4j.core.RrdBackendFactory;
import org.rrd4j.core.RrdDb;
import org.rrd4j.core.RrdDef;
import org.rrd4j.core.Sample;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * An implementation of control plane metrics back-end database.
 */
public final class DefaultMetricsDatabase implements MetricsDatabase {
    private String metricName;
    private RrdDb rrdDb;
    private Sample sample;
    private static final long SECONDS_OF_DAY = 60L * 60L * 24L;
    private static final long SECONDS_OF_MINUTE = 60L;
    private static final ConsolFun CONSOL_FUNCTION = ConsolFun.LAST;
    private static final String NON_EXIST_METRIC = "Non-existing metric type.";
    private static final String INSUFFICIENT_DURATION = "Given duration less than one minute.";
    private static final String EXCEEDED_DURATION = "Given duration exceeds a day time.";

    /**
     * Constructs a metrics database using the given metric name and
     * round robin database.
     *
     * @param metricName  metric name
     * @param rrdDb       round robin database
     */
    private DefaultMetricsDatabase(String metricName, RrdDb rrdDb) {
        this.metricName = metricName;
        this.rrdDb = rrdDb;
    }

    @Override
    public String metricName() {
        return this.metricName;
    }

    @Override
    public void updateMetric(String metricType, double value) {
        updateMetric(metricType, value, System.currentTimeMillis() / 1000L);
    }

    @Override
    public void updateMetric(String metricType, double value, long time) {
        try {
            checkArgument(rrdDb.containsDs(metricType), NON_EXIST_METRIC);
            sample = rrdDb.createSample(time);
            sample.setValue(metricType, value);
            sample.update();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void updateMetrics(Map<String, Double> metrics) {
        updateMetrics(metrics, System.currentTimeMillis() / 1000L);
    }

    @Override
    public void updateMetrics(Map<String, Double> metrics, long time) {
        try {
            sample = rrdDb.createSample(time);
            metrics.forEach((k, v) -> {
                try {
                    checkArgument(rrdDb.containsDs(k), NON_EXIST_METRIC);
                    sample.setValue(k, v);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            sample.update();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public double recentMetric(String metricType) {
        try {
            checkArgument(rrdDb.containsDs(metricType), NON_EXIST_METRIC);
            return rrdDb.getDatasource(metricType).getLastValue();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0D;
    }

    @Override
    public double[] recentMetrics(String metricType, int duration, TimeUnit unit) {
        try {
            checkArgument(rrdDb.containsDs(metricType), NON_EXIST_METRIC);
            long endTime = rrdDb.getLastUpdateTime();
            long startTime = endTime - TimeUnit.SECONDS.convert(duration, unit);
            if (checkTimeRange(startTime, endTime)) {
                FetchRequest fr = rrdDb.createFetchRequest(CONSOL_FUNCTION, startTime, endTime);
                return arrangeDataPoints(fr.fetchData().getValues(metricType));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new double[0];
    }

    @Override
    public double minMetric(String metricType) {
        try {
            checkArgument(rrdDb.containsDs(metricType), NON_EXIST_METRIC);
            long endTime = rrdDb.getLastUpdateTime() - 1;
            long startTime = endTime - SECONDS_OF_DAY + 1;
            return minMetric(metricType, startTime, endTime);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0D;
    }

    @Override
    public double maxMetric(String metricType) {
        try {
            checkArgument(rrdDb.containsDs(metricType), NON_EXIST_METRIC);
            long endTime = rrdDb.getLastUpdateTime();
            long startTime = endTime - SECONDS_OF_DAY;
            return maxMetric(metricType, startTime, endTime);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0D;
    }

    @Override
    public double[] metrics(String metricType) {
        try {
            checkArgument(rrdDb.containsDs(metricType), NON_EXIST_METRIC);
            long endTime = rrdDb.getLastUpdateTime();
            long startTime = endTime - SECONDS_OF_DAY;
            return metrics(metricType, startTime, endTime);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new double[0];
    }

    @Override
    public double[] metrics(String metricType, long startTime, long endTime) {
        try {
            checkArgument(rrdDb.containsDs(metricType), NON_EXIST_METRIC);
            if (checkTimeRange(startTime, endTime)) {
                FetchRequest fr = rrdDb.createFetchRequest(CONSOL_FUNCTION, startTime, endTime);
                return arrangeDataPoints(fr.fetchData().getValues(metricType));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new double[0];
    }

    @Override
    public long lastUpdate(String metricType) {
        try {
            checkArgument(rrdDb.containsDs(metricType), NON_EXIST_METRIC);
            rrdDb.getLastUpdateTime();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0L;
    }

    // try to check whether projected time range is within a day
    private boolean checkTimeRange(long startTime, long endTime) {
        // check whether the given startTime and endTime larger than 1 minute
        checkArgument(endTime - startTime >= SECONDS_OF_MINUTE, INSUFFICIENT_DURATION);

        // check whether the given start time and endTime smaller than 1 day
        checkArgument(endTime - startTime <= SECONDS_OF_DAY, EXCEEDED_DURATION);
        return true;
    }

    // try to remove first and last data points
    private double[] arrangeDataPoints(double[] data) {
        return Arrays.copyOfRange(data, 1, data.length - 1);
    }

    // obtains maximum metric value among projected range
    private double maxMetric(String metricType, long startTime, long endTime) {
        double[] all = metrics(metricType, startTime, endTime);
        List list = Arrays.asList(ArrayUtils.toObject(all));
        return (double) Collections.max(list);
    }

    // obtains minimum metric value among projected range
    private double minMetric(String metricType, long startTime, long endTime) {
        double[] all = metrics(metricType, startTime, endTime);
        List list = Arrays.asList(ArrayUtils.toObject(all));
        return (double) Collections.min(list);
    }

    public static final class Builder implements MetricsDatabase.Builder {
        private static final int RESOLUTION_IN_SECOND = 60;
        private static final String STORING_METHOD = "MEMORY";
        private static final DsType SOURCE_TYPE = DsType.GAUGE;
        private static final String DB_PATH = "CPMAN";
        private static final ConsolFun CONSOL_FUNCTION = ConsolFun.LAST;
        private static final double MIN_VALUE = 0;
        private static final double MAX_VALUE = Double.NaN;
        private static final double XFF_VALUE = 0.2;
        private static final int STEP_VALUE = 1;
        private static final int ROW_VALUE = 60 * 24;
        private static final String METRIC_NAME_MSG = "Must specify a metric name.";
        private static final String METRIC_TYPE_MSG = "Must supply at least a metric type.";

        private RrdDb rrdDb;
        private RrdDef rrdDef;
        private List<DsDef> dsDefs;
        private String metricName;

        public Builder() {
            // initialize data source definition list
            dsDefs = new ArrayList<>();
        }

        @Override
        public Builder withMetricName(String metricName) {
            this.metricName = metricName;

            // define the resolution of monitored metrics
            rrdDef = new RrdDef(DB_PATH + "_" + metricName, RESOLUTION_IN_SECOND);
            return this;
        }

        @Override
        public Builder addMetricType(String metricType) {
            dsDefs.add(defineSchema(metricType));
            return this;
        }

        @Override
        public MetricsDatabase build() {
            checkNotNull(metricName, METRIC_NAME_MSG);
            checkArgument(dsDefs.size() != 0, METRIC_TYPE_MSG);

            try {
                DsDef[] dsDefArray = new DsDef[dsDefs.size()];
                IntStream.range(0, dsDefs.size()).forEach(i -> dsDefArray[i] = dsDefs.get(i));

                rrdDef.addDatasource(dsDefArray);
                rrdDef.setStep(RESOLUTION_IN_SECOND);

                // raw archive, no aggregation is required
                ArcDef rawArchive = new ArcDef(CONSOL_FUNCTION, XFF_VALUE,
                        STEP_VALUE, ROW_VALUE);
                rrdDef.addArchive(rawArchive);

                // always store the metric data in memory...
                rrdDb = new RrdDb(rrdDef, RrdBackendFactory.getFactory(STORING_METHOD));
            } catch (IOException e) {
                e.printStackTrace();
            }

            return new DefaultMetricsDatabase(metricName, rrdDb);
        }

        private DsDef defineSchema(String metricType) {
            return new DsDef(metricType, SOURCE_TYPE, RESOLUTION_IN_SECOND,
                    MIN_VALUE, MAX_VALUE);
        }
    }
}
