package dangerzone.gui;
/*
 * This code is copyright Richard H. Clark, TheyCallMeDanger, OreSpawn, 2015-2020.
 * You may use this code for reference for modding the DangerZone game program,
 * and are perfectly welcome to cut'n'paste portions for your mod as well.
 * DO NOT USE THIS CODE FOR ANY PURPOSE OTHER THAN MODDING FOR THE DANGERZONE GAME.
 * DO NOT REDISTRIBUTE THIS CODE. 
 * 
 * This copyright remains in effect until January 1st, 2021. 
 * At that time, this code becomes public domain.
 * 
 * WARNING: There are bugs. Big bugs. Little bugs. Every size in-between bugs.
 * This code is NOT suitable for use in anything other than this particular game. 
 * NO GUARANTEES of any sort are given, either express or implied, and Richard H. Clark, 
 * TheyCallMeDanger, OreSpawn are not responsible for any damages, direct, indirect, or otherwise. 
 * You should have made backups. It's your own fault for not making them.
 * 
 * NO ATTEMPT AT SECURITY IS MADE. This code is USE AT YOUR OWN RISK.
 * Regardless of what you may think, the reality is, that the moment you 
 * connected your computer to the Internet, Uncle Sam, among many others, hacked it.
 * DO NOT KEEP VALUABLE INFORMATION ON INTERNET-CONNECTED COMPUTERS.
 * Or your phone...
 * 
 */



import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.Color;
import org.newdawn.slick.opengl.Texture;


import dangerzone.DangerZone;
import dangerzone.InventoryContainer;
import dangerzone.blocks.Blocks;
import dangerzone.items.Item;
import dangerzone.items.ItemArmor;
import dangerzone.items.Items;

/*
 * Only two routines you need to mess with when inheriting from this interface.
 * Call super() in your constructor,
 * and then override the process() routine.
 * That's it!
 * Call ImAllDone() when you don't want your GUI up any more.
 */
public class GuiInterface {
	
	public boolean escaped = false;
	public boolean entered = false;
	public InventoryContainer mousebite = null;

	//convenience... use it or not...
	public class ButtonHandler {
		Texture t;
		int x;
		int y;
		int xsize;
		int ysize;
		String s;
		InventoryContainer ic;
		
		public ButtonHandler(int xpos, int ypos, int bxsize, int bysize, Texture tx, String ot){
			x = xpos;
			y = ypos;
			xsize = bxsize;
			ysize = bysize;
			t = tx;
			s = ot;
			ic = null;
		}
		
		public ButtonHandler(int xpos, int ypos, int bxsize, int bysize, InventoryContainer iic){
			x = xpos;
			y = ypos;
			xsize = bxsize;
			ysize = bysize;
			t = null;
			s = null;
			ic = iic;
		}
		
		public void leftclickhandler(){			
		}
		public void rightclickhandler(){			
		}
		public void middleclickhandler(){			
		}
		
		public void draw(){
			if(ic != null){
				t = ic.getTexture();
				s = null;
				if(ic.count > 1){
					s = String.format("%d", ic.count);
				}
				if(t != null){
					GL11.glColor3f(1,1,1);
					drawRectangleWithTexture(t, x, y, xsize, ysize);
				}
				if(s != null && !s.equals("")){
					textAt( x+6, y, s);
					GL11.glColor3f(1,1,1); //because text messes this up!
				}
				//FIXME TODO - damage indicator! (if ic.count == 1 && ic.damage != 0 && ic.maxdamage != 0)
				if(ic.count == 1){
					if(ic.currentuses > 0){
						if(ic.getMaxStack() == 1){
							Item it = ic.getItem();
							if(it != null){
								int md = it.maxuses;
								if(md > 0){
									float pu = (float)ic.currentuses/(float)md;
									drawUsed(pu, x, y, xsize, 2);
								}
							}
						}
					}
				}
			}else{
				if(t != null){
					GL11.glColor3f(1,1,1);
					drawRectangleWithTexture(t, x, y, xsize, ysize);
				}
				if(s != null && !s.equals("")){
					textAt(x+6, y, s);
					GL11.glColor3f(1,1,1); //because text messes this up!
				}
			}
		}
	}
	
	public GuiInterface(){
		//nothing to do...
	}
	
	/*
	 * Do your thing here! Draw, and then process inputs, all in one go.
	 * You will get called approximately 60 times a second, same as the frame rate.
	 * Try not to slow things down too much!
	 * You are in menu-mode for drawing, with 0,0 in the lower left.
	 * DangerZone.screen_width and DangerZone.screen_height is the size.
	 * Completely over-ride this routine! 
	 * Don't call super() unless you want the keyboard and mouse queues cleared.
	 * OK, maybe last, before you return... lol!
	 */
	public void process(){		
		while(K_next()){}; //clear out the keyboard queue
		while(M_next()){}; //clear out the mouse queue
	}
	
	/*
	 * Clean exit from your gui, when you are all done.
	 */
	public void ImAllDone(){
		while(K_next()){}; //clear out the keyboard queue
		while(M_next()){}; //clear out the mouse queue
		DangerZone.clearActiveGui();
	}
	
	//convenience text routine! 
	//Remember to reset the brightness after drawing text!
	public void textAt( float xpos, float ypos, String text){
		DangerZone.wr.loadtexture(Blocks.stone.getTexture(0)); //it just wants a texture loaded, or it gets mad....
		GL11.glPushMatrix(); //save position
		GL11.glTranslatef(xpos, ypos+DangerZone.font.getHeight(), 0f); 
		GL11.glRotatef(180.0f, 1.0f, 0.0f, 0.0f); // Don't ask me why, but the text is upside down! Flip it!
		DangerZone.font.drawString(0, 0, text, Color.white);	
		GL11.glPopMatrix();  //restore position
	}
	
	//convenience box...
	public void drawRectangleWithTexture(Texture t, float xpos, float ypos, float xsize, float ysize){
		DangerZone.wr.forceloadtexture(t);
		float w = t.getWidth();
		float h = t.getHeight();
		GL11.glPushMatrix(); //save position
		GL11.glTranslatef(xpos, ypos, 0f); 
		GL11.glScalef(xsize/t.getWidth(), ysize/t.getHeight(), 1f);
		GL11.glBegin(GL11.GL_QUADS);	
		GL11.glTexCoord2f(w,0);
		GL11.glVertex3f(1, 1, 0); // Top Right
		GL11.glTexCoord2f(0,0);
		GL11.glVertex3f(0, 1, 0); // Top Left
		GL11.glTexCoord2f(0,h);
		GL11.glVertex3f(0, 0, 0); // Bottom left
		GL11.glTexCoord2f(w,h);
		GL11.glVertex3f(1, 0, 0); // Bottom right		
		GL11.glEnd(); // Done Drawing The Quad
		GL11.glPopMatrix();
	}
	
	//convenience box, with rotation...
	public void drawRectangleWithTexture(Texture t, float xpos, float ypos, float xsize, float ysize, float zrot){
		DangerZone.wr.forceloadtexture(t);
		float w = t.getWidth();
		float h = t.getHeight();
		GL11.glPushMatrix(); //save position
		GL11.glTranslatef(xpos, ypos, 0f); 
		//GL11.glPushMatrix(); //save position
		GL11.glRotatef(zrot, 0, 0, 1.0f);
		GL11.glScalef(xsize/t.getWidth(), ysize/t.getHeight(), 1f);
		GL11.glBegin(GL11.GL_QUADS);	
		GL11.glTexCoord2f(w,0);
		GL11.glVertex3f(1, 1, 0); // Top Right
		GL11.glTexCoord2f(0,0);
		GL11.glVertex3f(-1, 1, 0); // Top Left
		GL11.glTexCoord2f(0,h);
		GL11.glVertex3f(-1, -1, 0); // Bottom left
		GL11.glTexCoord2f(w,h);
		GL11.glVertex3f(1, -1, 0); // Bottom right		
		GL11.glEnd(); // Done Drawing The Quad
		//GL11.glPopMatrix();
		GL11.glPopMatrix();
	}
	
	//convenience box, with rotation...
	public void drawRectangleWithTextureTwo(Texture t, float xpos, float ypos, float xsize, float ysize, float zrot, float extrascale){
		DangerZone.wr.forceloadtexture(t);
		float w = t.getWidth();
		float h = t.getHeight();
		GL11.glPushMatrix(); //save position
		GL11.glTranslatef(xpos, ypos, 0f); 	
		GL11.glScalef(extrascale*xsize/t.getWidth(), extrascale*ysize/t.getHeight(), 1f);
		GL11.glRotatef(zrot, 0, 0, 1.0f);
		GL11.glBegin(GL11.GL_QUADS);	
		GL11.glTexCoord2f(w,0);
		GL11.glVertex3f(1, 1, 0); // Top Right
		GL11.glTexCoord2f(0,0);
		GL11.glVertex3f(-1, 1, 0); // Top Left
		GL11.glTexCoord2f(0,h);
		GL11.glVertex3f(-1, -1, 0); // Bottom left
		GL11.glTexCoord2f(w,h);
		GL11.glVertex3f(1, -1, 0); // Bottom right		
		GL11.glEnd(); // Done Drawing The Quad
		GL11.glPopMatrix();
	}
	
	public void drawUsed(float used, float xpos, float ypos, float xsize, float ysize){
		float xs;
		if(used > 1)used = 1;
		if(used < 0)used = 0;
		xs = xsize * (1f - used);
		if(xs < 1)xs = 1;
		GL11.glPushMatrix(); //save position
		GL11.glDisable(GL11.GL_TEXTURE_2D);
		GL11.glTranslatef(xpos, ypos, 0f); 
		GL11.glScalef(1f, 1f, 1f);
		GL11.glBegin(GL11.GL_QUADS);	
		GL11.glColor3f(used, 1f-used, 0);
		GL11.glVertex3f(xs, ysize, 0); // Top Right
		GL11.glColor3f(used, 1f-used, 0);
		GL11.glVertex3f(0, ysize, 0); // Top Left
		GL11.glColor3f(used, 1f-used, 0);
		GL11.glVertex3f(0, 0, 0); // Bottom left
		GL11.glColor3f(used, 1f-used, 0);
		GL11.glVertex3f(xs, 0, 0); // Bottom right		
		GL11.glEnd(); // Done Drawing The Quad
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glPopMatrix();
	}
	
	public void drawcoloredsquare(int xpos, int ypos, int xsize, int ysize, float r, float g, float b, float a){
		GL11.glPushMatrix(); //save position
		GL11.glDisable(GL11.GL_TEXTURE_2D);
		GL11.glEnable(GL11.GL_BLEND);
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		GL11.glTranslatef(xpos, ypos, 0f); 		
		GL11.glBegin(GL11.GL_QUADS);	
		GL11.glColor4f(r, g, b, a);
		GL11.glVertex3f(xsize, ysize, 0); // Top Right
		GL11.glColor4f(r, g, b, a);
		GL11.glVertex3f(0, ysize, 0); // Top Left
		GL11.glColor4f(r, g, b, a);
		GL11.glVertex3f(0, 0, 0); // Bottom left
		GL11.glColor4f(r, g, b, a);
		GL11.glVertex3f(xsize, 0, 0); // Bottom right		
		GL11.glEnd(); // Done Drawing The Quad
		GL11.glDisable(GL11.GL_BLEND);		
		GL11.glEnable(GL11.GL_TEXTURE_2D);	
		GL11.glPopMatrix();
	}
	
	/*
	 * You are in complete control of the keyboard and mouse inputs.
	 * Make sure you do the proper while() loops to clear the events.
	 * And yes, you have to go through these routines, because Mouse and Keyboard
	 * only have context in the main routine, nowhere else, and cannot be passed...
	 */
	public boolean K_next(){
		return DangerZone.K_next();
	}
	
	public int K_getEventKey(){
		return DangerZone.K_getEventKey();
	}
	
	public boolean K_getEventKeyState(){
		return DangerZone.K_getEventKeyState();
	}
	
	public boolean K_isKeyDown(int key){
		return DangerZone.K_isKeyDown(key);
	}
	
	public boolean M_next(){
		return DangerZone.M_next();
	}
	
	public int M_getEventButton(){
		return DangerZone.M_getEventButton();
	}
	
	public boolean M_getEventButtonState(){
		return DangerZone.M_getEventButtonState();
	}
	
	public int M_getEventX(){
		return DangerZone.M_getEventX();
	}
	
	public int M_getEventY(){
		return DangerZone.M_getEventY();
	}
	
	public int M_getX(){
		return DangerZone.M_getX();
	}
	
	public int M_getY(){
		return DangerZone.M_getY();
	}
	
	//gets one char at a time. returns null if none, "delete" if delete!
	//sets global "escaped" flag too...
	//and the "entered" flag...
	public String getTextChar(){
		int currk;
		boolean caps = false;
		escaped = false;
		entered = false;
		
		if(K_isKeyDown(Keyboard.KEY_LSHIFT)||K_isKeyDown(Keyboard.KEY_RSHIFT)){
			caps = true;
		}
		
		while (K_next()) {	
			//System.out.printf("Key!\n");
			if (K_getEventKey() == Keyboard.KEY_ESCAPE && K_isKeyDown(Keyboard.KEY_ESCAPE)){
				escaped = true;
			}
			if (K_getEventKey() == Keyboard.KEY_RETURN && K_isKeyDown(Keyboard.KEY_RETURN)){
				entered = true;
			}
			currk = K_getEventKey();
			if(!K_isKeyDown(currk))continue;
			
			switch(currk){
			
			case Keyboard.KEY_DELETE:
				return "delete";
			case Keyboard.KEY_BACK:
				return "delete";
				
			case Keyboard.KEY_0:
				if(caps)return ")";
				return "0";
			case Keyboard.KEY_1:
				if(caps)return "!";
				return "1";
			case Keyboard.KEY_2:
				if(caps)return "@";
				return "2";
			case Keyboard.KEY_3:
				if(caps)return "#";
				return "3";
			case Keyboard.KEY_4:
				if(caps)return "$";
				return "4";
			case Keyboard.KEY_5:
				if(caps)return "%";
				return "5";
			case Keyboard.KEY_6:
				if(caps)return "^";
				return "6";
			case Keyboard.KEY_7:
				if(caps)return "&";
				return "7";
			case Keyboard.KEY_8:
				if(caps)return "*";
				return "8";
			case Keyboard.KEY_9:
				if(caps)return "(";
				return "9";
			case Keyboard.KEY_A:
				if(caps)return "A";
				return "a";
			case Keyboard.KEY_B:
				if(caps)return "B";
				return "b";
			case Keyboard.KEY_C:
				if(caps)return "C";
				return "c";
			case Keyboard.KEY_D:
				if(caps)return "D";
				return "d";
			case Keyboard.KEY_E:
				if(caps)return "E";
				return "e";
			case Keyboard.KEY_F:
				if(caps)return "F";
				return "f";
			case Keyboard.KEY_G:
				if(caps)return "G";
				return "g";
			case Keyboard.KEY_H:
				if(caps)return "H";
				return "h";
			case Keyboard.KEY_I:
				if(caps)return "I";
				return "i";
			case Keyboard.KEY_J:
				if(caps)return "J";
				return "j";
			case Keyboard.KEY_K:
				if(caps)return "K";
				return "k";
			case Keyboard.KEY_L:
				if(caps)return "L";
				return "l";
			case Keyboard.KEY_M:
				if(caps)return "M";
				return "m";
			case Keyboard.KEY_N:
				if(caps)return "N";
				return "n";
			case Keyboard.KEY_O:
				if(caps)return "O";
				return "o";
			case Keyboard.KEY_P:
				if(caps)return "P";
				return "p";
			case Keyboard.KEY_Q:
				if(caps)return "Q";
				return "q";
			case Keyboard.KEY_R:
				if(caps)return "R";
				return "r";
			case Keyboard.KEY_S:
				if(caps)return "S";
				return "s";
			case Keyboard.KEY_T:
				if(caps)return "T";
				return "t";
			case Keyboard.KEY_U:
				if(caps)return "U";
				return "u";
			case Keyboard.KEY_V:
				if(caps)return "V";
				return "v";
			case Keyboard.KEY_W:
				if(caps)return "W";
				return "w";
			case Keyboard.KEY_X:
				if(caps)return "X";
				return "x";
			case Keyboard.KEY_Y:
				if(caps)return "Y";
				return "y";
			case Keyboard.KEY_Z:
				if(caps)return "Z";
				return "z";				
				
			case Keyboard.KEY_PERIOD:
				if(caps)return ">";
				return ".";
			case Keyboard.KEY_COMMA:
				if(caps)return "<";
				return ",";
			case Keyboard.KEY_SLASH:
				if(caps)return "?";
				return "/";				
			case Keyboard.KEY_SEMICOLON:
				if(caps)return ":";
				return ";";
			case Keyboard.KEY_APOSTROPHE:
				if(caps)return "\"";
				return "'";				
			case Keyboard.KEY_SPACE:
			case Keyboard.KEY_TAB:				
				return " ";				
			case Keyboard.KEY_BACKSLASH:
				if(caps)return "|";
				return "\\";
			case Keyboard.KEY_LBRACKET:
				if(caps)return "{";
				return "[";
			case Keyboard.KEY_RBRACKET:
				if(caps)return "}";
				return "]";				
			case Keyboard.KEY_MINUS:
				if(caps)return "_";
				return "-";
			case Keyboard.KEY_EQUALS:
				if(caps)return "+";
				return "=";
				
			default:
				
			}
		}
		return null;
	}
	
	//shift-click should call this...
	public void mousebiteToInventory(){
		if(mousebite == null)return;
		int i, df;
		InventoryContainer ic = null;
		
		//first search is to see if we can add to a stack
		for(i=0;i<50;i++){
			ic = DangerZone.player.getInventory(i);
			if(ic != null){
				if(ic.bid == mousebite.bid && ic.iid == mousebite.iid){
					df = 0;
					if(ic.bid != 0){
						df = Blocks.getMaxStack(ic.bid) - ic.count;
					}else{
						df = Items.getMaxStack(ic.iid) - ic.count;
					}
					if(df > 0){
						if(df >= mousebite.count){
							ic.count += mousebite.count;
							mousebite = null;
							break;
						}
						ic.count += df;
						mousebite.count -= df;
					}
					if(mousebite.count <= 0){
						mousebite = null;
						break;
					}
				}
			}			
		}
		if(mousebite == null){
			return;
		}
		//check the hotbar too!
		for(i=0;i<10;i++){
			ic = DangerZone.player.getHotbar(i);
			if(ic != null){
				if(ic.bid == mousebite.bid && ic.iid == mousebite.iid){
					df = 0;
					if(ic.bid != 0){
						df = Blocks.getMaxStack(ic.bid) - ic.count;
					}else{
						df = Items.getMaxStack(ic.iid) - ic.count;
					}
					if(df > 0){
						if(df >= mousebite.count){
							ic.count += mousebite.count;
							mousebite = null;
							break;
						}
						ic.count += df;
						mousebite.count -= df;
					}
					if(mousebite.count <= 0){
						mousebite = null;
						break;
					}
				}
			}			
		}
		if(mousebite == null){
			return;
		}
		
		//still have leftover. Find an empty slot
		for(i=0;i<50;i++){
			ic = DangerZone.player.getInventory(i);
			if(ic == null){
				DangerZone.player.setInventory(i, mousebite);
				mousebite = null;
				break;
			}			
		}
		if(mousebite == null){
			return;
		}
		for(i=0;i<10;i++){
			ic = DangerZone.player.getHotbar(i);
			if(ic == null){
				DangerZone.player.setHotbar(i, mousebite);
				mousebite = null;
				break;
			}			
		}			
	}
	
	public void showArmorValue(int which, int x, float scalex, int y, float scaley){
		InventoryContainer ic = DangerZone.player.getArmor(which);
		if(ic != null){
			if(ic.count == 1){
				Item it = ic.getItem();
				if(it instanceof ItemArmor){
					ItemArmor ia = (ItemArmor)it;
					String s = String.format("%3.1f", ia.protection);
					textAt( (x)*scalex, (y)*scaley, s);
					GL11.glColor3f(1,1,1); //because text messes this up!
				}
			}
		}
	}

}
