package ru.yandex.webmaster3.monitoring.queue.delurl;

import org.springframework.beans.factory.annotation.Required;
import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.solomon.SolomonSensor;
import ru.yandex.webmaster3.core.solomon.Indicators;
import ru.yandex.webmaster3.monitoring.common.YtQueueUtils;
import ru.yandex.webmaster3.storage.delurl.dao.DelUrlQueueYDao;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.storage.util.yt.YtService;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by ifilippov5 on 03.05.17.
 */
public class DelUrlPrefixMonitoringService {
    private static final String SECTION_DELURL_PREFIX_LABEL_VALUE = "delurl_prefix";
    private static final int SIZE_SENSORS_IN_BYTES = 300;
    private static final String YT_QUEUE_TYPE = "yt_queue";
    private static final String YDB_QUEUE_TYPE = "ydb_queue";

    private DelUrlQueueYDao delUrlQueueYDao;
    private YtService ytService;
    private YtPath ytRequestsPath;

    public List<SolomonSensor> createDelurlSensors(long time) throws Exception {
        List<SolomonSensor> sensors = new ArrayList<>();
        sensors.add(createQueueSizeSensor(getYdbQueueSize(), time, YDB_QUEUE_TYPE));
        sensors.add(createMaxAgeRecordSensor(getYdbMaxAgeRecordInSeconds(), time, YDB_QUEUE_TYPE));

        YtQueueUtils.QueueStats unprocessedYtRequestsStats = YtQueueUtils.getQueueStats(
                ytService, ytRequestsPath, YtQueueUtils.ALL_TABLES_FILTER, YtQueueUtils.JAVA_TIMESTAMP_EXTRACTOR);
        sensors.add(createQueueSizeSensor(unprocessedYtRequestsStats.tablesCount, time, YT_QUEUE_TYPE));
        sensors.add(createMaxAgeRecordSensor(unprocessedYtRequestsStats.maxAgeInMillis / 1000, time, YT_QUEUE_TYPE));

        return sensors;
    }

    public int getDelUrlSensorsSize() {
        return SIZE_SENSORS_IN_BYTES;
    }

    private long getYdbQueueSize() {
        try {
            return delUrlQueueYDao.count();
        } catch (WebmasterYdbException e) {
            throw new WebmasterException("Unable to get count",
                    new WebmasterErrorResponse.YDBErrorResponse(this.getClass(), e), e);
        }
    }

    private long getYdbMaxAgeRecordInSeconds() {
        try {
            return TimeUnit.MILLISECONDS.toSeconds(delUrlQueueYDao.maxAge());
        } catch (WebmasterYdbException e) {
            throw new WebmasterException("Unable to get max age",
                    new WebmasterErrorResponse.YDBErrorResponse(this.getClass(), e), e);
        }
    }

    protected static SolomonSensor createQueueSizeSensor(long queueSize, long timeAlignmentInSeconds, String dataType) {
        return SolomonSensor.createAligned(timeAlignmentInSeconds, queueSize)
                .withLabel(SolomonSensor.LABEL_SECTION, DelUrlPrefixMonitoringService.SECTION_DELURL_PREFIX_LABEL_VALUE)
                .withLabel(SolomonSensor.LABEL_INDICATOR, Indicators.QUEUE_SIZE)
                .withLabel(SolomonSensor.LABEL_DATA_TYPE, dataType);
    }

    protected static SolomonSensor createMaxAgeRecordSensor(long maxAge, long timeAlignmentInSeconds, String dataType) {
        return SolomonSensor.createAligned(timeAlignmentInSeconds, maxAge)
                .withLabel(SolomonSensor.LABEL_SECTION, DelUrlPrefixMonitoringService.SECTION_DELURL_PREFIX_LABEL_VALUE)
                .withLabel(SolomonSensor.LABEL_INDICATOR, Indicators.DATA_AGE)
                .withLabel(SolomonSensor.LABEL_DATA_TYPE, dataType);
    }

    @Required
    public void setYtService(YtService ytService) {
        this.ytService = ytService;
    }

    @Required
    public void setYtRequestsPath(YtPath ytRequestsPath) {
        this.ytRequestsPath = ytRequestsPath;
    }

    @Required
    public void setDelUrlQueueYDao(DelUrlQueueYDao delUrlQueueYDao) {
        this.delUrlQueueYDao = delUrlQueueYDao;
    }
}
