/* 
 
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz

This file is part of C.a.R. software.

    C.a.R. is a free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, version 3 of the License.

    C.a.R. is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 */
 
 
 package rene.viewer;

import java.awt.Color;
import java.awt.Graphics;

public class Line {
	TextDisplay TD;
	boolean Chosen;
	int Pos, Posend;
	int Block; // block state
	static final int NONE = 0, START = 1, END = 2, FULL = 4; // block states
	// (logically
	// or'ed)
	Color C, IC; // Color of line and high key color of the line
	char a[]; // Contains the characters of this line

	public Line(final String s, final TextDisplay td) {
		this(s, td, Color.black);
	}

	/**
	 * Generate a line containing s in the textdisplay td. Display color is c.
	 * 
	 * @param s
	 * @param td
	 * @param c
	 */
	public Line(final String s, final TextDisplay td, final Color c) {
		TD = td;
		C = c;
		// Create a color that is very bright, but resembles the line color
		IC = new Color(C.getRed() / 4 + 192, C.getGreen() / 4 + 192, C
				.getBlue() / 4 + 192);
		Block = NONE;
		a = s.toCharArray();
	}

	public void expandTabs(final int tabwidth) {
		int pos = 0;
		for (final char element : a) {
			pos++;
			if (element == '\t')
				pos = (pos / tabwidth + 1) * tabwidth;
		}
		final char b[] = new char[pos];
		pos = 0;
		for (final char element : a) {
			if (element == '\t') {
				final int newpos = ((pos + 1) / tabwidth + 1) * tabwidth;
				for (int k = pos; k < newpos; k++)
					b[k] = ' ';
				pos = newpos;
			} else
				b[pos++] = element;
		}
		a = b;
	}

	int length() {
		return a.length;
	}

	int getpos(final int x, final int offset) {
		final int l[] = TD.getwidth(a);
		int h = offset - TD.Offset * TD.FM.charWidth(' ');
		if (x < h)
			return 0;
		int i = 0;
		while (x > h && i < a.length) {
			h += l[i];
			i++;
		}
		return i;
	}

	/**
	 * Draw a line. If the line is in a block, draw it white on black or on dark
	 * gray, depending on the focus. Drawing in blocks does not use antialias.
	 * 
	 * @param g
	 * @param x
	 * @param y
	 */
	public void draw(final Graphics g, int x, final int y) {
		x -= TD.Offset * TD.FM.charWidth(' ');
		if (Chosen) // Complete line is chosen (in Lister)
		{ // To see, if the display has the focus:
			if (TD.hasFocus())
				g.setColor(Color.darkGray);
			else
				g.setColor(Color.gray);
			g.fillRect(0, y - TD.Ascent, TD.getSize().width, TD.Height);
			g.setColor(IC); // draw in light color
			TD.antialias(false);
			g.drawChars(a, 0, a.length, x, y);
			TD.antialias(true);
		} else if ((Block & FULL) != 0) // Line in full block (in Viewer)
		{
			g.setColor(Color.darkGray);
			g.fillRect(x, y - TD.Ascent, TD.FM.charsWidth(a, 0, a.length),
					TD.Height);
			g.setColor(Color.white);
			TD.antialias(false);
			g.drawChars(a, 0, a.length, x, y);
			TD.antialias(true);
		} else if ((Block & START) != 0) {
			if (Pos > 0) // Draw text before block
			{
				g.setColor(C);
				g.drawChars(a, 0, Pos, x, y);
				x += TD.FM.charsWidth(a, 0, Pos);
			}
			if ((Block & END) != 0) // draw text in block
			{
				if (Posend > Pos) {
					final int h = TD.FM.charsWidth(a, Pos, Posend - Pos);
					g.setColor(Color.darkGray);
					g.fillRect(x, y - TD.Ascent, h, TD.Height);
					g.setColor(Color.white);
					TD.antialias(false);
					g.drawChars(a, Pos, Posend - Pos, x, y);
					TD.antialias(true);
					g.setColor(C);
					x += h;
					if (a.length > Posend) {
						g.drawChars(a, Posend, a.length - Posend, x, y);
					}
				} else
					g.drawChars(a, Pos, a.length - Pos, x, y);
			} else // draw the rest of the line in block
			{
				final int h = TD.FM.charsWidth(a, Pos, a.length - Pos);
				g.setColor(Color.darkGray);
				g.fillRect(x, y - TD.Ascent, h, TD.Height);
				g.setColor(Color.white);
				TD.antialias(false);
				g.drawChars(a, Pos, a.length - Pos, x, y);
				TD.antialias(true);
			}
		} else if ((Block & END) != 0) {
			final int h = TD.FM.charsWidth(a, 0, Posend);
			g.setColor(Color.darkGray);
			g.fillRect(x, y - TD.Ascent, h, TD.Height);
			g.setColor(Color.white);
			TD.antialias(false);
			g.drawChars(a, 0, Posend, x, y);
			TD.antialias(true);
			g.setColor(C);
			x += h;
			if (a.length > Posend) {
				g.drawChars(a, Posend, a.length - Posend, x, y);
			}
		} else {
			g.setColor(C);
			g.drawChars(a, 0, a.length, x, y);
		}
	}

	void append(final String s) {
		a = (new String(a) + s).toCharArray();
	}

	void chosen(final boolean f) {
		Chosen = f;
	}

	public boolean chosen() {
		return Chosen;
	}

	void block(final int pos, final int mode) {
		switch (mode) {
		case NONE:
			Block = NONE;
			break;
		case FULL:
			Block = FULL;
			break;
		case START:
			Block |= START;
			Pos = pos;
			break;
		case END:
			Block |= END;
			Posend = pos;
			break;
		}
	}

	String getblock() {
		if (Block == FULL) {
			return new String(a, 0, a.length);
		} else if ((Block & START) != 0) {
			if ((Block & END) != 0) {
				return new String(a, Pos, Posend - Pos);
			} else
				return new String(a, Pos, a.length - Pos);
		} else if ((Block & END) != 0)
			return new String(a, 0, Posend);
		else
			return "";
	}
}
