/*
 * ConnectBot: simple, powerful, open-source SSH client for Android
 * Copyright 2007 Kenny Root, Jeffrey Sharkey
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.connectbot.util;

import de.mud.terminal.VDUBuffer;

/**
 * @author Kenny Root
 * Keep track of a selection area for the terminal copying mechanism.
 * If the orientation is flipped one way, swap the bottom and top or
 * left and right to keep it in the correct orientation.
 */
public class SelectionArea {
	private int top;
	private int bottom;
	private int left;
	private int right;
	private int maxColumns;
	private int maxRows;
	private boolean selectingOrigin;

	public SelectionArea() {
		reset();
	}

	public final void reset() {
		top = left = bottom = right = 0;
		selectingOrigin = true;
	}

	/**
	 * @param columns
	 * @param rows
	 */
	public void setBounds(int columns, int rows) {
		maxColumns = columns - 1;
		maxRows = rows - 1;
	}

	private int checkBounds(int value, int max) {
		if (value < 0)
			return 0;
		else if (value > max)
			return max;
		else
			return value;
	}

	public boolean isSelectingOrigin() {
		return selectingOrigin;
	}

	public void finishSelectingOrigin() {
		selectingOrigin = false;
	}

	public void decrementRow() {
		if (selectingOrigin)
			setTop(top - 1);
		else
			setBottom(bottom - 1);
	}

	public void incrementRow() {
		if (selectingOrigin)
			setTop(top + 1);
		else
			setBottom(bottom + 1);
	}

	public void setRow(int row) {
		if (selectingOrigin)
			setTop(row);
		else
			setBottom(row);
	}

	private void setTop(int top) {
		this.top = bottom = checkBounds(top, maxRows);
	}

	public int getTop() {
		return Math.min(top, bottom);
	}

	private void setBottom(int bottom) {
		this.bottom = checkBounds(bottom, maxRows);
	}

	public int getBottom() {
		return Math.max(top, bottom);
	}

	public void decrementColumn() {
		if (selectingOrigin)
			setLeft(left - 1);
		else
			setRight(right - 1);
	}

	public void incrementColumn() {
		if (selectingOrigin)
			setLeft(left + 1);
		else
			setRight(right + 1);
	}

	public void setColumn(int column) {
		if (selectingOrigin)
			setLeft(column);
		else
			setRight(column);
	}

	private void setLeft(int left) {
		this.left = right = checkBounds(left, maxColumns);
	}

	public int getLeft() {
		return Math.min(left, right);
	}

	private void setRight(int right) {
		this.right = checkBounds(right, maxColumns);
	}

	public int getRight() {
		return Math.max(left, right);
	}

	public String copyFrom(VDUBuffer vb) {
		int size = (getRight() - getLeft() + 1) * (getBottom() - getTop() + 1);

		StringBuffer buffer = new StringBuffer(size);

		for(int y = getTop(); y <= getBottom(); y++) {
			int lastNonSpace = buffer.length();

			for (int x = getLeft(); x <= getRight(); x++) {
				// only copy printable chars
				char c = vb.getChar(x, y);

				if (!Character.isDefined(c) ||
						(Character.isISOControl(c) && c != '\t'))
					c = ' ';

				if (c != ' ')
					lastNonSpace = buffer.length();

				buffer.append(c);
			}

			// Don't leave a bunch of spaces in our copy buffer.
			if (buffer.length() > lastNonSpace)
				buffer.delete(lastNonSpace + 1, buffer.length());

			if (y != bottom)
				buffer.append("\n");
		}

		return buffer.toString();
	}

	@Override
	public String toString() {
		StringBuilder buffer = new StringBuilder();

		buffer.append("SelectionArea[top=");
		buffer.append(top);
		buffer.append(", bottom=");
		buffer.append(bottom);
		buffer.append(", left=");
		buffer.append(left);
		buffer.append(", right=");
		buffer.append(right);
		buffer.append(", maxColumns=");
		buffer.append(maxColumns);
		buffer.append(", maxRows=");
		buffer.append(maxRows);
		buffer.append(", isSelectingOrigin=");
		buffer.append(isSelectingOrigin());
		buffer.append("]");

		return buffer.toString();
	}
}
