package com.lanyuanxiaoyao.service.sync.metrics;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import com.lanyuanxiaoyao.service.common.entity.FlinkJob;
import com.lanyuanxiaoyao.service.common.entity.TableMeta;
import com.lanyuanxiaoyao.service.sync.configuration.GlobalConfiguration;
import com.lanyuanxiaoyao.service.sync.utils.MetricsUtils;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.LongAdder;

/**
 * 基础类
 *
 * @author ZhangJiacheng
 * @date 2022-06-13
 */
public class RateMetric extends AbstractMetric {
    private final LongAdder count = new LongAdder();

    private final HttpMetricsRequest countMetrics;
    private final HttpMetricsRequest millisecondMetrics;
    private final HttpMetricsRequest perSecondMetrics;

    private final Instant startInstant;

    public RateMetric(GlobalConfiguration globalConfiguration, String name) {
        this(globalConfiguration, name, MapUtil.empty());
    }

    public RateMetric(GlobalConfiguration globalConfiguration, String name, FlinkJob job, TableMeta meta) {
        this(globalConfiguration, name, MapUtil.builder(MetricsUtils.commonTags(job, meta)).build());
    }

    public RateMetric(GlobalConfiguration globalConfiguration, String name, FlinkJob job, TableMeta meta, String extraTagKey, String extraTagValue) {
        this(globalConfiguration, name, job, meta, MapUtil.of(extraTagKey, extraTagValue));
    }

    public RateMetric(GlobalConfiguration globalConfiguration, String name, FlinkJob job, TableMeta meta, Map<String, String> tags) {
        this(globalConfiguration, name, MapUtil.builder(MetricsUtils.commonTags(job, meta))
                .putAll(tags)
                .build());
    }

    public RateMetric(GlobalConfiguration globalConfiguration, String name, Map<String, String> tags) {
        super(globalConfiguration);

        startInstant = Instant.now();

        countMetrics = new HttpMetricsRequest(
                name + "_count",
                MapUtil.<String, String>builder().putAll(tags).build()
        );
        millisecondMetrics = new HttpMetricsRequest(
                name + "_millisecond",
                MapUtil.<String, String>builder().putAll(tags).build()
        );
        perSecondMetrics = new HttpMetricsRequest(
                name + "_per_millisecond",
                MapUtil.<String, String>builder().putAll(tags).build()
        );
        setRequests(countMetrics, millisecondMetrics, perSecondMetrics);
    }

    public void increment() {
        count.increment();
    }

    @Override
    public void makePoint() {
        double count = this.count.doubleValue();
        if (count != 0) {
            long millis = Duration.between(startInstant, Instant.now()).toMillis();
            countMetrics.addMetric(count);
            millisecondMetrics.addMetric((double) millis);
            perSecondMetrics.addMetric(count / millis);
        }
    }

    @Override
    public List<HttpMetricsRequest> getMetrics() {
        return ListUtil.toList(countMetrics, millisecondMetrics, perSecondMetrics);
    }
}
