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

import java.util.List;
import java.util.function.Consumer;

import org.lwjgl.glfw.GLFW;

import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.coreengine.math.color.ColorUtils;
import speiger.src.coreengine.rendering.guiOld.GuiComponent;
import speiger.src.coreengine.rendering.guiOld.base.IKeyComponent;
import speiger.src.coreengine.rendering.guiOld.components.ListComponent;
import speiger.src.coreengine.rendering.guiOld.components.ScrollBarComponent;
import speiger.src.coreengine.rendering.guiOld.components.TextFieldComponent;
import speiger.src.coreengine.rendering.guiOld.components.list.TextListEntry;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.Constrains;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.ParentConstrain;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.PixelConstrain;
import speiger.src.coreengine.rendering.guiOld.helper.constrains.RelativeConstrain;
import speiger.src.coreengine.rendering.guiOld.renderer.IFontRenderer;

public class ConsoleComponent extends GuiComponent implements IKeyComponent
{
	TextFieldComponent chat = new TextFieldComponent(ColorUtils.DARK_GRAY).setCanLoseFocus(false).setInfiniteText(true).setMaxTextLength(Integer.MAX_VALUE).setFocused(true);
	ListComponent<MessageEntry> list = new ListComponent<>(ColorUtils.setA(ColorUtils.DARK_GRAY, 120), 8F); 
	float lastWidth = 0F;
	List<ConsoleMessage> messages = new ObjectArrayList<>();
	Consumer<String> listener;
	int messageIterator = 0;
	boolean started = false;
	
	public ConsoleComponent()
	{
		this(0F, 0F, 0F, 0F);
	}
	
	public ConsoleComponent(float x, float y, float width, float height)
	{
		super(x, y, width, height);
	}
	
	public ConsoleComponent setListener(Consumer<String> listener)
	{
		this.listener = listener;
		return this;
	}
	
	@Override
	public void init()
	{
		chat.getRawText().setTextScale(0.45F);
		chat.onAction(this::onEnter);
		list.setSelectionMode(ListComponent.SELECTION_MODE_DISABLE);
		list.setStartAtBottom(true);
		addChild(chat, new Constrains(new ParentConstrain(), new ParentConstrain(12F).invert(), new ParentConstrain(), new PixelConstrain(12F)));
		addChild(list, new Constrains(new ParentConstrain(), new ParentConstrain(100).invert(), new RelativeConstrain(0.8F), new PixelConstrain(88)));
	}
	
	@Override
	protected void updateState()
	{
		float width = list.getBox().getWidth();
		if(lastWidth != width)
		{
			lastWidth = width;
			updateMessages();
		}
	}
	
	protected void updateMessages()
	{
		list.clear();
		for(int i = 0,m=messages.size();i<m;i++)
		{
			ConsoleMessage message = messages.get(i);
			addMessage(message.getMessage(), message.getMessageId(), false);
		}
	}
	
	public void toggleVisiblity()
	{
		setVisible(!isVisible());
		chat.setFocused(isVisible());
	}
	
	private void onEnter()
	{
		if(!chat.isVisible())
		{
			chat.setText("");
			return;
		}
		if(chat.getText().isEmpty()) return;
		addMessage(chat.getText(), 0);
		chat.setText("");
	}
	
	@Override
	public boolean isAcceptingInput()
	{
		return isVisible();
	}
	
	@Override
	public boolean isBlockingMovement()
	{
		return true;
	}
	
	@Override
	public boolean onKeyPressed(int key)
	{
		if(key == GLFW.GLFW_KEY_UP)
		{
			if(messageIterator < messages.size())
			{
				chat.setText(messages.get((messages.size()-1 - messageIterator)).getMessage()).setCurserToEnd();
				messageIterator++;
				started = true;
			}
			return true;
		}
		else if(key == GLFW.GLFW_KEY_DOWN)
		{
			if(messageIterator > 0)
			{
				messageIterator--;
				chat.setText(messages.get((messages.size()-1 - messageIterator)).getMessage()).setCurserToEnd();
			}
			else if(started)
			{
				chat.setText("").setCurserToEnd();
				started = false;
			}
			return true;
		}
		return false;
	}

	public void addMessage(String text)
	{
		addMessage(text, 0);
	}
	
	public void addMessage(String text, int messageId)
	{
		addMessage(text, messageId, true);
	}
	
	private void addMessage(String text, int messageId, boolean add)
	{
		if(listener != null && text.startsWith("/"))
		{
			listener.accept(text.substring(1));
			return;
		}
		ScrollBarComponent scroll = list.getVerticalBar();
		boolean atEnd = scroll.isAtEnd();
		float width = (list.getBox().getWidth() -5F) / 0.45F;
		for(String s : getGui().getFont().split(text, width, IFontRenderer.SPECIAL))
		{
			list.add(new MessageEntry(s, messageId));
		}
		if(atEnd) scroll.setScrollEnd();
		if(add) 
		{
			messages.add(new ConsoleMessage(messageId, text));
			messageIterator = 0;
		}
	}
	
	public void clearMessages()
	{
		messages.clear();
		list.clear();
		messageIterator = 0;
	}
	
	public void removeMessage(int messageId)
	{
		messages.removeIf(T -> T.getMessageId() == messageId);
		list.removeIf(T -> T.getMessageId() == messageId);
	}
	
	private static class ConsoleMessage
	{
		int messageId;
		String message;
		
		public ConsoleMessage(int messageId, String message)
		{
			this.messageId = messageId;
			this.message = message;
		}
		
		public String getMessage()
		{
			return message;
		}
		
		public int getMessageId()
		{
			return messageId;
		}
	}
	
	private static class MessageEntry extends TextListEntry
	{
		int messageId;
		
		public MessageEntry(String s, int messageId)
		{
			super(s);
			this.messageId = messageId;
			setScale(0.45F);
		}
		
		public int getMessageId()
		{
			return messageId;
		}
	}
}