package ru.yandex.webmaster3.storage.util.yt;

import org.joda.time.Duration;
import org.joda.time.Instant;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author aherman
 */
class YtTransaction {
    private final String cluster;
    private final String id;
    private final String parentId;
    private final Duration timeout;
    private final long pingIntervalMs;

    private volatile Instant lastPingTime;
    private volatile Instant nextPingTime;
    private AtomicInteger pingRetryCount = new AtomicInteger();

    private final ConcurrentHashMap<YtPath, YtLockMode> locks = new ConcurrentHashMap<>();

    private volatile boolean closed = false;

    YtTransaction(String parentId, String cluster, String id, Duration timeout, long pingIntervalMs) {
        this.cluster = cluster;
        this.id = id;
        this.parentId = parentId;
        this.timeout = timeout;
        this.pingIntervalMs = pingIntervalMs;
    }

    void ping(Instant now, Instant nextPingTime) {
        this.lastPingTime = now;
        this.nextPingTime = nextPingTime;
        this.pingRetryCount.set(0);
    }

    String getCluster() {
        return cluster;
    }

    String getId() {
        return id;
    }

    long getPingIntervalMs() {
        return pingIntervalMs;
    }

    Instant getNextPingTime() {
        return nextPingTime;
    }

    AtomicInteger getPingRetryCount() {
        return pingRetryCount;
    }

    void close() {
        closed = true;
    }

    boolean isClosed() {
        return closed;
    }

    boolean hasLock(YtPath path) {
        return locks.contains(path);
    }

    YtLockMode getLock(YtPath path) {
        return locks.get(path);
    }

    void addLock(YtPath path, YtLockMode mode) {
        locks.put(path, mode);
    }

    @Override
    public String toString() {
        String mess = "";
        if (parentId != null) {
            mess += "parent_tx=" + parentId + " ";
        }
        mess += "tx=" + id + " timeout=" + timeout + " lastPing=" + lastPingTime;
        return mess;
    }
}
