package com.mall4j.cloud.leaf.segment.model;

import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 双buffer
 *
 * @author left
 */
public class SegmentBuffer {

	private String key;

	/**
	 * 双buffer
	 */
	private final Segment[] segments;

	/**
	 * 当前的使用的segment的index
	 */
	private volatile int currentPos;

	/**
	 * 下一个segment是否处于可切换状态
	 */
	private volatile boolean nextReady;

	/**
	 * 是否初始化完成
	 */
	private volatile boolean initOk;

	/**
	 * 线程是否在运行中
	 */
	private final AtomicBoolean threadRunning;

	private final ReadWriteLock lock;

	private volatile int step;

	private volatile int minStep;

	private volatile long updateTimestamp;

	public SegmentBuffer() {
		segments = new Segment[] { new Segment(this), new Segment(this) };
		currentPos = 0;
		nextReady = false;
		initOk = false;
		threadRunning = new AtomicBoolean(false);
		lock = new ReentrantReadWriteLock();
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public Segment[] getSegments() {
		return segments;
	}

	public Segment getCurrent() {
		return segments[currentPos];
	}

	public int getCurrentPos() {
		return currentPos;
	}

	public int nextPos() {
		return (currentPos + 1) % 2;
	}

	public void switchPos() {
		currentPos = nextPos();
	}

	public boolean isInitOk() {
		return !initOk;
	}

	public void setInitOk(boolean initOk) {
		this.initOk = initOk;
	}

	public boolean isNextReady() {
		return nextReady;
	}

	public void setNextReady(boolean nextReady) {
		this.nextReady = nextReady;
	}

	public AtomicBoolean getThreadRunning() {
		return threadRunning;
	}

	public Lock rLock() {
		return lock.readLock();
	}

	public Lock wLock() {
		return lock.writeLock();
	}

	public int getStep() {
		return step;
	}

	public void setStep(int step) {
		this.step = step;
	}

	public int getMinStep() {
		return minStep;
	}

	public void setMinStep(int minStep) {
		this.minStep = minStep;
	}

	public long getUpdateTimestamp() {
		return updateTimestamp;
	}

	public void setUpdateTimestamp(long updateTimestamp) {
		this.updateTimestamp = updateTimestamp;
	}

	@Override
	public String toString() {
		final StringBuilder sb = new StringBuilder("SegmentBuffer{");
		sb.append("key='").append(key).append('\'');
		sb.append(", segments=").append(Arrays.toString(segments));
		sb.append(", currentPos=").append(currentPos);
		sb.append(", nextReady=").append(nextReady);
		sb.append(", initOk=").append(initOk);
		sb.append(", threadRunning=").append(threadRunning);
		sb.append(", step=").append(step);
		sb.append(", minStep=").append(minStep);
		sb.append(", updateTimestamp=").append(updateTimestamp);
		sb.append('}');
		return sb.toString();
	}

}
