package client.gui.element;

import client.gui.Font;
import client.renderer.Drawing;
import client.renderer.Drawing.Offset;
import client.renderer.Drawing.Vec2i;
import common.util.CharValidator;
import common.util.ExtMath;
import common.util.Util;

public class Field extends Textbox {
	private int textWidth;
	private int scrollPos;
	private int cursorPos;

	private Field(int x, int y, int w, int h, int cap, boolean editable, FieldCallback callback, CharValidator validator, String text) {
		super(x, y, w, h, cap, editable, callback, validator);
		this.text_y = (this.size_y - (this.margin_y1 + this.margin_y2 + Font.HEIGHT)) / 2;
		this.setText(text);
	}
	
	public Field(int x, int y, int w, int h, int cap, FieldCallback callback, CharValidator validator, String text) {
		this(x, y, w, h, cap, true, callback, validator, text);
	}

	public Field(int x, int y, int w, int h, int cap, FieldCallback callback, String text) {
		this(x, y, w, h, cap, true, callback, null, text);
	}
	
	public Field(int x, int y, int w, int h, String text) {
		this(x, y, w, h, Integer.MAX_VALUE, false, null, null, text);
	}
	
	public void updateText() {
		this.textWidth = Drawing.txt_size(this.pos_x + this.margin_x1, this.pos_y + this.margin_y1, 
				this.pos_x + this.margin_x1, this.pos_y + this.margin_y1, 
				Integer.MAX_VALUE, Integer.MAX_VALUE, this.getDrawnText()).xpos;
	}
	
	public void mouserel() {
		this.scrollPos = 0;
	}
	
	public void onReturn(boolean shift) {
		if(this.func != null) {
			this.func.use(this, shift ? FieldAction.LINE : FieldAction.SEND);
		}
	}
	
	public void onSelection(boolean up) {
		if(this.func != null) {
			this.func.use(this, up ? FieldAction.PREVIOUS : FieldAction.NEXT);
		}
	}
	
	public void update() {
		if(this.scrollPos != 0) {
			int n = this.updateScroll(this.scrollPos);
			this.text_x += n;
			if(n != 0)
				gui_text_clamp_scroll();
		}
	}
	
	public void shift(int shift_x, int shift_y) {
		super.shift(shift_x, shift_y);
		this.cursorPos += shift_x;
	}
	
	public void scroll(int scr_x, int scr_y, int x, int y, boolean ctrl, boolean shift) {
		if(scr_y != 0 || scr_x != 0) {
			int limit = Font.WIDTH + this.textWidth - (this.size_x - (this.margin_x1 + this.margin_x2));
			limit = ExtMath.clampi(limit, 0, 0x7fffffff);
			int prev = this.text_x;
			this.text_x += ((scr_y != 0 ? scr_y : (-scr_x)) < 0 ? -1 : 1) * (ctrl ? 1 : Font.WIDTH) * this.gm.scrollLines * (shift ? 10 : 1);
			this.text_x = ExtMath.clampi(this.text_x, -limit, 0);
			if(this.sel_start >= 0)
				this.cursorPos += (this.text_x - prev);
		}
	}
	
	protected int getCursorX(int x1, int x2) {
		return this.cursorPos;
	}
	
	protected int getCursorY(int y1, int y2) {
		return y1 + (y2 - Font.HEIGHT) / 2;
	}
	
	protected void gui_text_clamp_scroll() {
		int limit = Font.WIDTH + this.textWidth - (this.size_x - (this.margin_x1 + this.margin_x2));
		limit = ExtMath.clampi(limit, 0, 0x7fffffff);
		this.text_x = ExtMath.clampi(this.text_x, -limit, 0);
	}
	
	protected void updateCursor(int offset, boolean shift, int x1, int y1, int x2, int y2) {
		Vec2i coord = Drawing.txt_coord(offset, x1 + this.text_x, y1 + this.text_y, 
			x1 + this.text_x, y1 + this.text_y, 0x7fffffff, 0x7fffffff, this.getDrawnText());
		this.cursorPos = coord.xpos;
		if(shift) {
			if(this.cursorPos < x1)
				this.text_x += x1 - this.cursorPos;
			else if((this.cursorPos + Font.WIDTH) >= (x1 + x2))
				this.text_x -= (this.cursorPos + Font.WIDTH) - (x1 + x2);
			gui_text_update_cur(offset, false);
		}
	}
	
	protected int onCursorOffset(int x, int y, int x1, int y1, int x2, int y2) {
		Offset off = Drawing.txt_offset(x, y, x1 + this.text_x, y1 + this.text_y, 
			x1 + this.text_x, y1 + this.text_y, 0x7fffffff, 0x7fffffff, this.getDrawnText());
		if(off != null) {
			this.cursorPos = off.xpos;
		}
		int offset = off == null ? 0 : off.offset;
		if(x < x1)
			this.scrollPos = x1 - x;
		else if(x >= (x1 + x2))
			this.scrollPos = -(x - (x1 + x2));
		return offset;
	}

	protected void drawBackground() {
		if(this.enabled)
			Drawing.drawGradientBorder(this.pos_x, this.pos_y, this.size_x, this.size_y, this.gm.style.field_top, this.gm.style.field_btm, 0xff000000, this.gm.style.brdr_top, this.gm.style.brdr_btm);
		else
			Drawing.drawGradientBorder(this.pos_x, this.pos_y, this.size_x, this.size_y, Util.mulColor(this.gm.style.field_top, 0.5f), Util.mulColor(this.gm.style.field_btm, 0.5f), 0xff000000, Util.mulColor(this.gm.style.brdr_top, 0.5f), Util.mulColor(this.gm.style.brdr_btm, 0.5f));
	}
	
	protected void drawForeground(int x1, int y1, int x2, int y2) {
		Drawing.txt_draw(x1 + this.text_x, y1 + this.text_y, 
				x1 + this.text_x, y1 + this.text_y, 
				Integer.MAX_VALUE, Integer.MAX_VALUE, this.enabled ? this.gm.style.text_field : Util.mulColor(this.gm.style.text_field, 0.5f), this.getDrawnText());
		if(this.sel_start >= 0 && this.sel_end != this.sel_start)
			Drawing.txt_overlay(this.sel_start, this.sel_end, x1 + this.text_x, y1 + this.text_y, 
				x1 + this.text_x, y1 + this.text_y, 
				Integer.MAX_VALUE, Integer.MAX_VALUE, this.enabled ? 0x808080ff : 0x80404040, this.getDrawnText());
	}
	
	protected char getNewline() {
		return ' ';
	}
	
	protected String getDrawnText() {
		return this.text;
	}
	
	
	
	



	public void deleteSpaceToCur() {
		int num = this.getSpaceBeforeCur() - this.sel_start;
		if(this.text.length() != 0) {
			if(this.sel_start != this.sel_end) {
				this.insertText("");
			}
			else {
//				boolean flag = num < 0;
				int i = this.sel_start + num; // flag ? this.sel_start + num : this.sel_start;
				int j = this.sel_start; // flag ? this.sel_start : this.sel_start + num;
				String s = "";

				if(i >= 0) {
					s = this.text.substring(0, i);
				}

				if(j < this.text.length()) {
					s = s + this.text.substring(j);
				}

//				this.setText(s);
				this.text = s;
				this.updateText();
				this.sel_start = this.sel_end = this.sel_drag = i;
				gui_text_update_cur(this.sel_start, true);
//
//				if(flag) {
//					this.moveCursorBy(num);
//				}
			}
		}
	}

	public int getSpaceBeforeCur() {
		int i = this.sel_start;
		while(i > 0 && this.text.charAt(i - 1) != ' ') {
			--i;
		}
		return i;
	}
	
	public int getCursorPos() {
		return this.sel_start == this.sel_end ? this.sel_start : -1;
	}
}
