/*
	Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
	и других спецификаций для функционирования компактных приложений на языке
	Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

	Copyright © 2016, 2019 Малик Разработчик

	Это свободная программа: вы можете перераспространять ее и/или изменять
	ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
	в каком она была опубликована Фондом свободного программного обеспечения;
	либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

	Эта программа распространяется в надежде, что она будет полезной,
	но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
	или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
	общественной лицензии GNU.

	Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
	вместе с этой программой. Если это не так, см.
	<https://www.gnu.org/licenses/>.
*/


package javax.microedition.lcdui;

import malik.emulator.media.graphics.*;

public class StringItem extends Item
{
	private boolean controlFocused;
	private boolean pointerFocused;
	private boolean pointerPressed;
	private int contentWidth;
	private int contentHeight;
	private int appearance;
	private String text;
	private Font font;
	private TextOutputMultilined lines;

	public StringItem(String label, String text)
	{
		this(LAYOUT_DEFAULT, -1, -1, label, null, null, null, text, null, PLAIN);
	}

	public StringItem(String label, String text, int appearance)
	{
		this(LAYOUT_DEFAULT, -1, -1, label, null, null, null, text, null, appearance);
	}

	public StringItem(int layout, int lockedWidth, int lockedHeight, String label,
			Command[] commands, Command defaultCommand, ItemCommandListener listener,
			String text, Font font, int appearance)
	{
		super(layout, lockedWidth, lockedHeight, label, commands, defaultCommand, listener);
		Font f;
		TextOutputMultilined lines;
		if(appearance != PLAIN && appearance != HYPERLINK && appearance != BUTTON)
		{
			throw new IllegalArgumentException("StringItem: " +
					"недопустимое значение параметра appearance.");
		}
		this.appearance = appearance;
		this.text = text;
		this.font = font != null ? font :
				(appearance != HYPERLINK ? Font.getFont(Font.FONT_STATIC_TEXT) :
				Font.getFont((f = Font.getFont(Font.FONT_STATIC_TEXT)).getFace(),
				f.getStyle() | Font.STYLE_UNDERLINED, f.getSize()));
		this.lines = lines = new TextOutputMultilinedExt(0);
		lines.setText(text);
	}

	public void setText(String text)
	{
		TextOutputMultilined lines;
		this.text = text;
		synchronized(lines = this.lines)
		{
			lines.setText(text);
		}
		notifyUpdate();
	}
	
	public void setFont(Font font)
	{
		this.font = font == null ? Font.getFont(Font.FONT_STATIC_TEXT) : font;
		notifyUpdate();
	}

	public int getAppearanceMode()
	{
		return appearance;
	}

	public String getText()
	{
		return text;
	}
	
	public Font getFont()
	{
		return font;
	}

	void paintContent(Graphics render, int contentWidth, int contentHeight)
	{
		boolean pressed;
		int l;
		int t;
		int a;
		int s;
		int ct;
		int cb;
		int i;
		int len;
		char[] chars;
		TextOutputMultilined lines;
		Font font;
		pressed = pointerPressed;
		render.setFont(font = this.font);
		synchronized(lines = this.lines)
		{
			lines.split(font, contentWidth - 8);
			s = font.getHeight();
			cb = (ct = render.getClipY()) + render.getClipHeight();
			len = lines.getLinesCount();
			chars = lines.getChars();
			if(isMatchForButton())
			{
				render.drawElementOfGUI(4, a = pressed ? 1 : (controlFocused ? 3 : 0), 0,
						0, 0, contentWidth, contentHeight);
				render.setColor(RasterCanvas.getSystemColor(a + 0x24));
				l = (contentWidth / 2) + (pressed ? 1 : 0);
				t = ((contentHeight - len * s) / 2) + (pressed ? 1 : 0);
				a = Graphics.HCENTER | Graphics.TOP;
			}
			else if(isMatchForHyperlink())
			{
				a = pressed ? 1 : (controlFocused ? 3 : 0);
				render.setColor(RasterCanvas.getSystemColor(a + 0x24));
				l = pressed ? 5 : 4;
				t = pressed ? 5 : 4;
				a = Graphics.LEFT | Graphics.TOP;
			}
			else
			{
				render.setColor(RasterCanvas.getSystemColor(0x28));
				l = 4;
				t = 4;
				a = Graphics.LEFT | Graphics.TOP;
			}
			for(i = 0; i < len; t += s, i++)
			{
				if(t < cb && t + s > ct)
				{
					render.drawChars(chars, lines.getLineStart(i), lines.getLineLength(i),
							l, t, a);
				}
			}
		}
	}

	void onSizeChanged(int contentWidth, int contentHeight)
	{
		this.contentWidth = contentWidth;
		this.contentHeight = contentHeight;
	}

	void onContentPointerPressed(int x, int y, int button)
	{
		if(button != MIDletProxy.BUTTON_MAIN ||
				(!isMatchForButton()) && (!isMatchForHyperlink()))
		{
			return;
		}
		pointerFocused = true;
		pointerPressed = true;
		notifyPaint();
	}

	void onContentPointerDragged(int x, int y)
	{
		if((!pointerFocused) || pointerPressed == (pointerPressed =
				x >= 0 && x < contentWidth &&
				y >= 0 && y < contentHeight))
		{
			return;
		}
		notifyPaint();
	}

	void onContentPointerReleased(int x, int y, int button)
	{
		boolean pressed;
		if(button != MIDletProxy.BUTTON_MAIN)
		{
			return;
		}
		pressed = pointerPressed;
		pointerFocused = false;
		pointerPressed = false;
		if(!pressed)
		{
			return;
		}
		notifyPaint();
		notifyCommandAction(getCommands().getDefaultCommand());
	}

	void onTraverseOut()
	{
		controlFocused = false;
		if(isMatchForButton())
		{
			notifyPaint();
		}
	}

	boolean onTraverseNeedStayOn(int direction, int viewportWidth, int viewportHeight,
			int[] visibleRectangle)
	{
		boolean cfocused;
		int tmp;
		int size;
		if((cfocused = controlFocused) != (controlFocused = true) && isMatchForButton())
		{
			notifyPaint();
		}
		if(pointerFocused)
		{
			return true;
		}
		switch(direction)
		{
		case Canvas.UP:
			if(cfocused)
			{
				if((tmp = visibleRectangle[TOP]) > 0)
				{
					visibleRectangle[TOP] = Math.max(tmp - viewportHeight / 4, 0);
					return true;
				}
				return false;
			}
			break;
		case Canvas.LEFT:
			if(cfocused)
			{
				if((tmp = visibleRectangle[LEFT]) > 0)
				{
					visibleRectangle[LEFT] = Math.max(tmp - viewportWidth / 4, 0);
					return true;
				}
				return false;
			}
			break;
		case Canvas.RIGHT:
			size = super.getPreferredWidth() - visibleRectangle[WIDTH];
			if(cfocused)
			{
				if((tmp = visibleRectangle[LEFT]) < size)
				{
					visibleRectangle[LEFT] = Math.min(tmp + viewportWidth / 4, size);
					return true;
				}
				return false;
			}
			break;
		case Canvas.DOWN:
			size = super.getPreferredHeight() - visibleRectangle[HEIGHT];
			if(cfocused)
			{
				if((tmp = visibleRectangle[TOP]) < size)
				{
					visibleRectangle[TOP] = Math.min(tmp + viewportHeight / 4, size);
					return true;
				}
				return false;
			}
			break;
		}
		return true;
	}

	boolean isMatchForButton()
	{
		return appearance == BUTTON && super.isMatchForButton();
	}

	boolean isMatchForHyperlink()
	{
		return appearance == HYPERLINK && super.isMatchForHyperlink();
	}

	int getPreferredContentWidth(int contentHeight, int containerClientWidth)
	{
		int i;
		int tmp;
		int result;
		char[] chars;
		Font font;
		TextOutputMultilined lines;
		result = 0;
		font = this.font;
		synchronized(lines = this.lines)
		{
			chars = lines.getChars();
			lines.split(font, Integer.MAX_VALUE - 8);
			for(i = lines.getLinesCount(); i-- > 0; )
			{
				if(result < (tmp = font.charsWidth(chars,
						lines.getLineStart(i), lines.getLineLength(i))))
				{
					result = tmp;
				}
			}
		}
		if((result += 8) > containerClientWidth)
		{
			result = containerClientWidth;
		}
		return result;
	}

	int getPreferredContentHeight(int contentWidth)
	{
		int result;
		Font font;
		TextOutputMultilined lines;
		font = this.font;
		if(contentWidth < 0)
		{
			contentWidth = Integer.MAX_VALUE;
		}
		synchronized(lines = this.lines)
		{
			lines.split(font, contentWidth - 8);
			result = lines.getLinesCount() * font.getHeight() + 8;
		}
		return result;
	}
}
