package speiger.src.coreengine.rendering.guiOld.components;

import speiger.src.coreengine.math.color.ColorUtils;
import speiger.src.coreengine.rendering.guiOld.GuiComponent;
import speiger.src.coreengine.rendering.guiOld.helper.Align;
import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox;
import speiger.src.coreengine.rendering.guiOld.renderer.FontRenderer;
import speiger.src.coreengine.rendering.guiOld.renderer.buffer.RenderBuffer;
import speiger.src.coreengine.rendering.guiOld.renderer.lexer.TextMetadata;

public class TextComponent extends GuiComponent
{
	public static final int FLAG_STRIKE_THROUGH = 1 << 20;
	public static final int FLAG_UNDERLINE = 1 << 21;
	public static final int FLAG_BOLD = 1 << 22;
	public static final int FLAG_FORMATTING = 1 << 23;
	public static final int FLAG_FLIPPED = 1 << 24;
	public static final int FLAG_LIMITED_WIDTH = 1 << 25;
	public static final int FLAG_LIMITED_HEIGHT = 1 << 26;
	public static final int FLAG_AUTO_SCALE = 1 << 27;
	public static final int FLAG_SINGLE_LINE = 1 << 28;
	
	FontRenderer font;
	String text = "";
	Align vertical = Align.CENTER;
	Align horizontal = Align.CENTER;
	int textColor = ColorUtils.WHITE;
	Integer backGroundColor = null;
	float italic = 0F;
	float textScale = 1F;
	RenderBuffer buffer;
	float initialSize;
	TextMetadata metadata = new TextMetadata(this);
	
	public TextComponent()
	{
		super(0F, 0F, 0F, 0F);
		setFlag(FLAG_FORMATTING | FLAG_LIMITED_WIDTH | FLAG_LIMITED_HEIGHT);
	}
	
	public TextComponent(String text)
	{
		this(0F, 0F, 0F, 0F, text);
	}
	
	public TextComponent(float x, float y, float width, float height)
	{
		super(x, y, width, height);
		setFlag(FLAG_FORMATTING | FLAG_LIMITED_WIDTH | FLAG_LIMITED_HEIGHT);
	}
	
	public TextComponent(float x, float y, float width, float height, String text)
	{
		super(x, y, width, height);
		setFlag(FLAG_FORMATTING | FLAG_LIMITED_WIDTH | FLAG_LIMITED_HEIGHT);
		setText(text);
	}
	
	@Override
	public void init()
	{
		onClose(buffer = getRenderer().createBuffer());
		if(font == null)
		{
			setFont(getGui().getFont());
		}
		initialSize = getBox().getWidth();
	}
	
	@Override
	public boolean renderSelf(int mouseX, int mouseY, float particalTicks)
	{
		if(text.isEmpty())
		{
			return true;
		}
		float minX = getBox().getMinX();
		float minY = getBox().getMinY();
		getRenderer().translate(minX, minY).setActiveTexture(font.getTexture()).drawBuffers(buffer, getBox().getWidth(), getBox().getHeight()).translate(-minX, -minY);
		return true;
	}
	
	@Override
	public void calculateActualBounds(float[] area, boolean start)
	{
		if(start)
		{
			area[0] = Float.MAX_VALUE;
			area[1] = Float.MAX_VALUE;
			area[2] = Float.MIN_VALUE;
			area[3] = Float.MIN_VALUE;
		}
		IGuiBox box = getBox();
		area[0] = Math.min(area[0], box.getMinX() - metadata.getStartX());
		area[1] = Math.min(area[1], box.getMinY() - metadata.getStartY());
		area[2] = Math.max(area[2], (box.getMinX() - metadata.getStartX()) + metadata.getMaxWidth());
		area[3] = Math.max(area[3], (box.getMinY() - metadata.getStartY()) + metadata.getMaxHeight());
		for(GuiComponent comp : getChildren())
		{
			if(comp.isVisible()) comp.calculateActualBounds(area, false);
		}
	}
	
	public RenderBuffer getBuffer()
	{
		return buffer;
	}
	
	@Override
	protected void repaint()
	{
		metadata.clear();
		if(font == null)
		{
			return;
		}
		font.updateText(this);
	}
	
	public TextComponent setTextScale(float textScale)
	{
		if(this.textScale != textScale)
		{
			this.textScale = textScale;
			onChanged(true);
		}
		return this;
	}
	
	public TextMetadata getMetadata()
	{
		return metadata;
	}
	
	public final float getTextScale()
	{
		return textScale * getBox().getScale() * (isAutoScaling() ? getBox().getWidth() / initialSize : 1F);
	}
	
	public final float getRawTextScale()
	{
		return textScale * (isAutoScaling() ? getBox().getWidth() / initialSize : 1F);
	}
	
	public final float getWidth()
	{
		return getBox().getWidth() / getTextScale();
	}
	
	public final float getItalic()
	{
		return italic;
	}
	
	public final boolean isBold()
	{
		return isFlagSet(FLAG_BOLD);
	}
	
	public final boolean isStrikeThrough()
	{
		return isFlagSet(FLAG_STRIKE_THROUGH);
	}
	
	public final boolean isUnderlined()
	{
		return isFlagSet(FLAG_UNDERLINE);
	}
	
	public final boolean isFlipped()
	{
		return isFlagSet(FLAG_FLIPPED);
	}
	
	public final boolean isRenderingSpecial()
	{
		return isFlagSet(FLAG_FORMATTING);
	}
	
	public final boolean isWidthLimited()
	{
		return isFlagSet(FLAG_LIMITED_WIDTH);
	}
	
	public final boolean isHeightLimited()
	{
		return isFlagSet(FLAG_LIMITED_HEIGHT);
	}
	
	public final boolean isLimitedText()
	{
		return isFlagSet(FLAG_LIMITED_WIDTH | FLAG_LIMITED_HEIGHT);
	}
	
	public final boolean isAutoScaling()
	{
		return isFlagSet(FLAG_AUTO_SCALE);
	}
	
	public final boolean isForcedSingleLine()
	{
		return isFlagSet(FLAG_SINGLE_LINE);
	}
	
	public final int getTextColor()
	{
		return textColor;
	}
	
	public final Integer getBackgroundColor()
	{
		return backGroundColor;
	}
	
	@Override
	public FontRenderer getFont()
	{
		return font;
	}
	
	public String getText()
	{
		return text;
	}
	
	public String getText(int min)
	{
		return text.substring(min);
	}
	
	public String getText(int min, int max)
	{
		return text.substring(min, max);
	}
	
	public int length()
	{
		return text.length();
	}
	
	public Align getVertical()
	{
		return vertical;
	}

	public Align getHorizontal()
	{
		return horizontal;
	}
	
	public final TextComponent bold(boolean value)
	{
		if(setFlag(FLAG_BOLD, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent strikethrough(boolean value)
	{
		if(!setFlag(FLAG_STRIKE_THROUGH, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent underline(boolean value)
	{
		if(!setFlag(FLAG_UNDERLINE, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent flipped(boolean value)
	{
		if(!setFlag(FLAG_FLIPPED, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent special(boolean value)
	{
		if(!setFlag(FLAG_FORMATTING, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent limit(boolean value)
	{
		if(!setFlag(FLAG_LIMITED_HEIGHT | FLAG_LIMITED_WIDTH, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent limitWidth(boolean value)
	{
		if(!setFlag(FLAG_LIMITED_WIDTH, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent limitHeight(boolean value)
	{
		if(!setFlag(FLAG_LIMITED_HEIGHT, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent autoScale(boolean value)
	{
		if(!setFlag(FLAG_AUTO_SCALE, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent singleLine(boolean value)
	{
		if(!setFlag(FLAG_SINGLE_LINE, value))
		{
			return this;
		}
		onChanged(true);
		return this;
	}
	
	public final TextComponent italic(boolean value)
	{
		return italic(value ? 3F : 0F);
	}
	
	public final TextComponent italic(float value)
	{
		if(italic != value)
		{
			italic = value;
			onChanged(true);
		}
		return this;
	}
	
	public TextComponent align(Align horizontal, Align vertical)
	{
		if(this.horizontal != horizontal || this.vertical != vertical)
		{
			this.horizontal = horizontal;
			this.vertical = vertical;
			onChanged(true);
		}
		return this;
	}
	
	public TextComponent horizontal(Align horizontal)
	{
		if(this.horizontal != horizontal)
		{
			this.horizontal = horizontal;
			onChanged(true);
		}
		return this;
	}
	
	public TextComponent vertical(Align vertical)
	{
		if(this.vertical != vertical)
		{
			this.vertical = vertical;
			onChanged(true);
		}
		return this;
	}
	
	public TextComponent setText(String text)
	{
		if(text == null) text = "null";
		if(!this.text.equals(text))
		{
			this.text = text;
			onChanged(true);
		}
		return this;
	}
	
	public TextComponent textColor(int color)
	{
		if(textColor != color)
		{
			textColor = color;
			onChanged(true);
		}
		return this;
	}
	
	public TextComponent backgroundColor(int color)
	{
		if(backGroundColor != color)
		{
			backGroundColor = color;
			onChanged(true);
		}
		return this;
	}
	
	public TextComponent setFont(FontRenderer font)
	{
		if(this.font != font)
		{
			this.font = font;
			onChanged(true);
		}
		return this;
	}
}
