package ru.yandex.market.graphouse.server;

import org.springframework.beans.factory.annotation.Value;
import ru.yandex.market.graphouse.Metric;
import ru.yandex.market.graphouse.MetricUtil;
import ru.yandex.market.graphouse.MetricValidator;
import ru.yandex.market.graphouse.search.MetricSearch;
import ru.yandex.market.graphouse.search.MetricStatus;
import ru.yandex.market.graphouse.search.tree.MetricDescription;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author Dmitry Andreev <a href="mailto:AndreevDm@yandex-team.ru"></a>
 * @date 08/05/15
 */
public class MetricFactory {

    private final MetricSearch metricSearch;
    private final MetricValidator metricValidator;

    @Value("${graphouse.host-metric-redirect.enabled}")
    private boolean redirectHostMetrics = true;

    @Value("${graphouse.host-metric-redirect.dir}")
    private String hostMetricDir = "HOST";

    @Value("${graphouse.host-metric-redirect.postfixes}")
    private List<String> hostPostfixes = Collections.emptyList();

    public MetricFactory(MetricSearch metricSearch, MetricValidator metricValidator) {
        this.metricSearch = metricSearch;
        this.metricValidator = metricValidator;
    }

    /**
     * Validates the metric and, if successful, creates or updates the current one.
     *
     * @param line  contains name of the metric, value, timestamp
     * @param updatedSeconds
     * @return Created or updated metric,
     * <code>null</code> if the metric name or value is not valid, the metric is banned
     */
    public Metric createMetric(String line, int updatedSeconds) {

        String[] splits = line.split(" ");
        if (splits.length != 3) {
            return null;
        }
        String name = processName(splits[0]);
        String[] nameSplits = MetricUtil.splitToLevels(name);
        //Trying to fast find metric in tree. In success we can skip validation;
        MetricDescription metric = metricSearch.maybeFindMetric(nameSplits);
        if (metric == null) {
            if (!metricValidator.validate(name, false)) {
                return null;
            }
            metric = metricSearch.add(name);
            if (metric == null){
                return null;
            }
        } else if (metric.getStatus() == MetricStatus.AUTO_HIDDEN || metric.getStatus() == MetricStatus.HIDDEN) {
            metric = metricSearch.add(name);
        }
        if (metric.getStatus() == MetricStatus.BAN) {
            return null;
        }

        try {
            double value = Double.parseDouble(splits[1]);
            if (!Double.isFinite(value)) {
                return null;
            }
            int timeSeconds = Integer.valueOf(splits[2]);
            if (timeSeconds <= 0) {
                return null;
            }
            return new Metric(metric, timeSeconds, value, updatedSeconds);
        } catch (NumberFormatException e) {
            return null;
        }
    }

    public String processName(String name) {
        if (!redirectHostMetrics) {
            return name;
        }
        String[] splits = name.split("\\.", 3);
        for (int i = 0; i < hostPostfixes.size(); i++) {
            if (splits[1].endsWith(hostPostfixes.get(i))) {
                return splits[0] + "." + hostMetricDir + "." + splits[1] + "." + splits[2];
            }
        }
        return name;
    }

    public void setRedirectHostMetrics(boolean redirectHostMetrics) {
        this.redirectHostMetrics = redirectHostMetrics;
    }

    public void setHostMetricDir(String hostMetricDir) {
        this.hostMetricDir = hostMetricDir;
    }

    public void setHostPostfixes(String hostPostfixes) {
        this.hostPostfixes = Arrays.asList(hostPostfixes.split(","));
    }
}

@@ -2706,23 +2706,43 @@
 s = 
-Integer.valueOf
+(int) Math.round(Double.parseDouble
 (spl
@@ -2748,16 +2748,17 @@
 lits%5B2%5D)
+)
 ;%0A      

Add support for float timestamp values (#52)