package it.cavallium.warppi.gui.expression;

import it.cavallium.warppi.gui.expression.blocks.BlockContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockOrContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockPosition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;

public class Caret {

	@NotNull
	private BlockPosition pos;
	private CaretState state;
	private final int[] lastSize;
	private final int[] lastLocation;

	public Caret(final CaretState state, final BlockPosition pos) {
		this(state, pos, new int[] { 0, 0 }, new int[] { 2, 5 });
	}

	public Caret(final CaretState state, final @NotNull BlockPosition pos, final int[] lastLocation, final int[] lastSize) {
		this.state = state;
		this.pos = pos;
		this.lastLocation = lastLocation;
		this.lastSize = lastSize;
	}

	/**
	 * Copy
	 * @param old
	 */
	public Caret(Caret old, BlockContainer newRoot) {
		this.pos = clonePosition(old.pos, newRoot);
		this.state = old.state;
		this.lastSize = Arrays.copyOf(old.lastSize, old.lastSize.length);
		this.lastLocation = Arrays.copyOf(old.lastLocation, old.lastLocation.length);
	}

	private BlockPosition clonePosition(BlockPosition pos, BlockContainer newRoot) {
		BlockOrContainer el = newRoot;
		var url = pos.getURL();
		for (int i : url) {
			el = el.getAt(i);
		}
		return new BlockPosition(el);
	}

	@NotNull
	public BlockPosition getPos() {
		return pos;
	}

	public CaretState getState() {
		return state;
	}

	public void flipState() {
		if (state == CaretState.VISIBLE_ON) {
			state = CaretState.VISIBLE_OFF;
		} else if (state == CaretState.VISIBLE_OFF) {
			state = CaretState.VISIBLE_ON;
		}
	}

	public void turnOn() {
		if (state == CaretState.VISIBLE_OFF) {
			state = CaretState.VISIBLE_ON;
		}
	}

	public void setPosition(final BlockPosition pos) {
		this.pos = pos;
	}

	public void setLastLocation(final int x, final int y) {
		lastLocation[0] = x;
		lastLocation[1] = y;
	}

	public int[] getLastLocation() {
		return new int[] { lastLocation[0], lastLocation[1] };
	}

	public void setLastSize(final int w, final int h) {
		lastSize[0] = w;
		lastSize[1] = h;
	}

	public int[] getLastSize() {
		return new int[] { lastSize[0], lastSize[1] };
	}

	public boolean isHere(BlockOrContainer pos) {
		return getPos().get() == pos;
	}
}
