package client.gui.ingame;

import client.gui.Gui;
import client.gui.element.ActButton;
import client.gui.element.ButtonCallback;
import client.gui.element.Element;
import client.gui.element.Label;
import client.gui.element.NavButton;
import client.gui.element.PasswordField;
import client.gui.element.PressType;
import client.gui.element.Switch;
import client.gui.element.SwitchCallback;
import client.gui.element.FieldAction;
import client.gui.element.Field;
import client.gui.element.FieldCallback;
import client.gui.element.Toggle;
import client.gui.element.ToggleCallback;
import client.network.ClientPlayer;
import common.packet.CPacketForm;
import common.util.ExtMath;
import common.util.Color;
import common.util.Triplet;

public class GuiForm extends Gui implements ButtonCallback {
	private final int id;
	private final String title;
	private final Element[] inputs;
	private final Label[] labels;
	private final Triplet<String, Object, Integer>[] inputData;
	private final Object[] outputData;
	
	private boolean sent;
	
	public void init(int width, int height) {
		this.add(new Label(0, -100, 300, 0, this.title));
		for(int z = 0; z < this.inputs.length; z++) {
			final int index = z;
			final String name = this.inputData[z].first();
			Object obj = this.inputData[z].second();
			int param = this.inputData[z].third();
			if(obj instanceof Boolean bool) {
				this.inputs[z] = this.add(new Toggle(0, 50 * z, 300, 0, bool, bool, new ToggleCallback() {
					public void use(Toggle elem, boolean value) {
						GuiForm.this.outputData[index] = value;
					}
				}, name));
			}
			else if(obj instanceof String[] strs) {
				param = ExtMath.clampi(param, 0, strs.length - 1);
				this.inputs[z] = this.add(new Switch<String>(0, 50 * z, 300, 0, strs, strs[param], strs[param], new SwitchCallback<String>() {
					public void use(Switch<String> elem, String value) {
						for(int n = 0; n < strs.length; n++) {
							if(value == strs[n]) {
								GuiForm.this.outputData[index] = n;
								break;
							}
						}
					}
				}, name));
			}
			else {
				this.labels[z] = this.add(new Label(0, 50 * z, 300, name, true));
				FieldCallback callback = new FieldCallback() {
					public void use(Field elem, FieldAction value) {
						if(value == FieldAction.FOCUS)
							GuiForm.this.labels[index].setText(name);
					}
				};
				this.inputs[z] = this.add((param & 0x80000000) != 0 ? new PasswordField(0, 50 * z, 300, 0, Math.min(param & 0xffff, 1024), callback, (String)obj) :
					new Field(0, 50 * z, 300, 0, Math.min(param & 0xffff, 1024), callback, (String)obj));
			}
		}
		this.add(new NavButton(0, 50 * (this.inputs.length + 1), 148, 0, null, "Abbrechen"));
		this.add(new ActButton(152, 50 * (this.inputs.length + 1), 148, 0, this, "Senden"));
		this.shift();
	}
	
	public String getTitle() {
		return this.title;
	}
    
    public void onGuiClosed() {
    	if(!this.sent) {
	        ClientPlayer nethandler = this.gm.getNetHandler();
	        if(nethandler != null) {
		        nethandler.addToSendQueue(new CPacketForm(this.id, null));
	        }
    	}
    }
    
    public GuiForm(int id, String title, Triplet<String, Object, Integer>[] data) {
    	this.id = id;
    	this.title = title;
    	this.inputs = new Element[data.length];
    	this.labels = new Label[data.length];
    	this.inputData = data;
    	this.outputData = new Object[data.length];
		for(int z = 0; z < data.length; z++) {
			Object obj = data[z].second();
			this.outputData[z] = obj instanceof String[] ? data[z].third() : obj;
		}
    }
	
	public void use(ActButton elem, PressType action) {
		for(int z = 0; z < this.inputs.length; z++) {
			if(this.inputs[z] instanceof Field) {
				int min = (this.inputData[z].third() & 0x7fffffff) >> 16;
				String text = this.inputs[z].getText();
				if(text.length() < min) {
					if(!GuiForm.this.labels[z].getText().startsWith("" + Color.RED))
						GuiForm.this.labels[z].setText(Color.RED + GuiForm.this.labels[z].getText());
					return;
				}
				this.outputData[z] = text;
			}
		}
		this.sent = true;
        ClientPlayer nethandler = this.gm.getNetHandler();
        if(nethandler != null) {
	        nethandler.addToSendQueue(new CPacketForm(this.id, this.outputData));
        }
        this.gm.show(null);
	}
}
