package edu.wisc.cs.games10.chrononaut;

import processing.core.*;

//Camera determines what is visible onscreen
class Camera {
	float leftx;
	float rightx;
	float screenwidth;
	float halfwidth;
	
	float topy;
	float bottomy;
	float screenheight;
	float halfheight;
	
	int width;
	int height;
	int tilesize;
	
	PImage pastImage;
	PImage presentImage;
	PImage futureImage;
	
	PImage pastBack;
	PImage presentBack;
	PImage futureBack;
	
	PImage squares[];
	Square[][]pastSquares;
	Square[][]presentSquares;
	Square[][]futureSquares;
	

	/** Camera:
	 * 
	 * @param width: screen size in pixels
	 * @param height: screen size in pixels
	 * @param tilesize: size of a single tile in pixels
	 */
	Camera(int w, int h, int ts) {
		width = w;
		height = h;
		tilesize = ts;
		
		// how many tiles to show for the given width
		screenwidth = width / (float) tilesize;
		halfwidth = screenwidth / 2;
		leftx = 0;
		rightx = screenwidth;

		// how many tiles to show for the given height
		screenheight = height / (float) tilesize;
		halfheight = screenheight / 2;
		topy = 0;
		bottomy = screenheight;
		
		
	}
	
	public void setImages(Level l, PApplet canvas) {
		pastImage = l.getForeground(Era.PAST);
		canvas.texture(pastImage);
		presentImage = l.getForeground(Era.PRESENT);
		canvas.texture(presentImage);
		futureImage = l.getForeground(Era.FUTURE);
		canvas.texture(futureImage);
		
		pastBack = l.getBackground(Era.PAST);
		canvas.texture(pastBack);
		presentBack = l.getBackground(Era.PRESENT);
		canvas.texture(presentBack);
		futureBack = l.getBackground(Era.FUTURE);
		canvas.texture(futureBack);
	}
	
	public void setSquares(SquareLevel l, PApplet canvas) {
		pastBack = l.getBackground(Era.PAST);
		canvas.texture(pastBack);
		presentBack = l.getBackground(Era.PRESENT);
		canvas.texture(presentBack);
		futureBack = l.getBackground(Era.FUTURE);
		canvas.texture(futureBack);
		squares = l.getImages();
	}

	public void center(Level l, Vector2D loc) {
		// snap to edges
		if (loc.x < halfwidth) {
			leftx = 0;
		} else if (loc.x > l.getWidth() - halfwidth) {
			leftx = l.getWidth() - screenwidth;
		} else {
			leftx = loc.x - halfwidth;
		}

		// we'll always be the same width
		rightx = leftx + screenwidth;
		
		// snap to edges
		if (loc.y < halfheight) {
			topy = 0;
		} else if (loc.y > l.getHeight() - halfheight) {
			topy = l.getHeight() - screenheight;
		} else {
			topy = loc.y - halfheight;
		}

		// we'll always be the same height
		bottomy = topy + screenheight;
	}
	
	public void renderBackground(PApplet canvas, Era era) {
		
		
		int left = -(((int) (leftx * 10)) % width);
		int right = left + width;
		if(era == Era.PAST) {
			canvas.image(pastBack, left, 0);
			canvas.image(pastBack, right, 0);
		} else if(era == Era.PRESENT) {
			canvas.image(presentBack, left, 0);
			canvas.image(presentBack, right, 0);
		} else {
			canvas.image(futureBack, left, 0);
			canvas.image(futureBack, right, 0);
		}
		/*canvas.image(background, left, 0);
		canvas.image(background, right, 0);*/
	}
	
	public void renderForeground2(PApplet canvas, Era era, int timepeak, Level l) {
		Square[][] currentSquares;
		Era nextEra = era; // default to our own time!
		Tile[][] peekTiles = null;
		
		
		
		if(era == Era.PAST) {
			currentSquares = l.pastSquares;
			if(timepeak == -1) {
				peekTiles = l.futuretiles;
				nextEra = Era.FUTURE;
			} else if(timepeak == 1) {
				peekTiles = l.presenttiles;
				nextEra = Era.PRESENT;
			}
		} else if(era == Era.PRESENT) {
			currentSquares = l.presentSquares;
			if(timepeak == -1) {
				peekTiles = l.pasttiles;
				nextEra = Era.PAST;
			} else if(timepeak == 1) {
				peekTiles = l.futuretiles;
				nextEra = Era.FUTURE;
			}
		} else {
			currentSquares = l.futureSquares;
			if(timepeak == -1) {
				peekTiles = l.presenttiles;
				nextEra = Era.PRESENT;
			} else if(timepeak == 1) {
				peekTiles = l.pasttiles;
				nextEra = Era.PAST;
			}
		}
		
		for(int x = (int)leftx; x<rightx; x++) {
			for(int y= (int)topy; y<bottomy; y++) {
				// get tile image
				PImage tileImage = null;
				if (currentSquares[x][y] != Square.BLANK_TILE) {
					tileImage = squares[currentSquares[x][y].index];
				}
				
				// draw the current tile
				canvas.beginShape(PConstants.QUADS);
				if (tileImage != null) {
					canvas.texture(tileImage);
					canvas.vertex(x, y,  0, 0);
					canvas.vertex(x+1, y, 32, 0);
					canvas.vertex(x+1, y+1, 32, 32);
					canvas.vertex(x, y+1, 0, 32);
				}
				canvas.endShape();
				
				// preview solid tiles
				if(peekTiles != null && peekTiles[x][y] == Tile.SOLID) {
					canvas.fill(0,0,0,25);
					canvas.beginShape(PConstants.QUADS);
						canvas.vertex(x, y);
						canvas.vertex(x+1, y);
						canvas.vertex(x+1, y+1);
						canvas.vertex(x, y+1);
					canvas.endShape();
				}
			}
		}
		
		// preview the creatures
		if (peekTiles != null) {
			for (Creature c : l.creatures) {
				if ( c.era == nextEra ) {
					canvas.tint(255,255,255,25);
					c.render(canvas);
					canvas.noTint();
				}
			}
		}
	}
	
	public void renderForeground(PApplet canvas, Era era, int timepeak) {
		int lefttile = (int) Math.floor(leftx * tilesize);
		int toptile = (int) Math.floor(topy * tilesize);

		PImage mapchunk;
		if(era == Era.PAST) {
			//mapchunk = pastImage.get(lefttile, toptile, width, height);
			mapchunk = pastImage;
		} else if(era == Era.PRESENT){
			//mapchunk = presentImage.get(lefttile, toptile, width, height);
			mapchunk = presentImage;
		} else {
			mapchunk = futureImage;
			//mapchunk = futureImage.get(lefttile, toptile, width, height);
		}
		
		/* USES TEXTURES AND TINT */
		canvas.beginShape(PConstants.QUADS);
			canvas.texture(mapchunk);
			canvas.vertex(0, 0, lefttile, toptile);
			canvas.vertex(width, 0, lefttile+width,toptile);
			canvas.vertex(width, height, lefttile+width,toptile+height);
			canvas.vertex(0, height, lefttile,toptile+height);
		canvas.endShape();
	
		if(timepeak == -1) {
			PImage peakchunk;
			if(era == Era.PRESENT){
				peakchunk = pastImage;
			} else if(era == Era.FUTURE){
				peakchunk = presentImage;
			} else {
				peakchunk = futureImage;
			}
			canvas.tint(200, 200, 200, 50); 

			canvas.beginShape(PConstants.QUADS);
				canvas.texture(peakchunk);
				canvas.vertex(0, 0, lefttile, toptile);
				canvas.vertex(width, 0, lefttile+width,toptile);
				canvas.vertex(width, height, lefttile+width,toptile+height);
				canvas.vertex(0, height, lefttile,toptile+height);
			canvas.endShape();
			canvas.noTint();
		} else if(timepeak == 1) {
			PImage peakchunk;
			if(era == Era.PAST){
				peakchunk = presentImage;
			} else if(era == Era.PRESENT){
				peakchunk = futureImage;
			} else {
				peakchunk = pastImage;
			}
			canvas.tint(200, 200, 200, 50);  

			canvas.beginShape(PConstants.QUADS);
				canvas.texture(peakchunk);
				canvas.vertex(0, 0, lefttile, toptile);
				canvas.vertex(width, 0, lefttile+width,toptile);
				canvas.vertex(width, height, lefttile+width,toptile+height);
				canvas.vertex(0, height, lefttile,toptile+height);
			canvas.endShape();
			canvas.noTint();
		}
		
		
		
	}
	
	/** draws a grid over tile boundaries */
	public void renderGrid(PApplet canvas) {
		canvas.strokeWeight(1.0f / 32);
		canvas.stroke(200);
		
		// draw horizontal lines
		int iTopY = (int) Math.ceil(topy);
		while (iTopY < bottomy) {
			canvas.line(leftx, iTopY, rightx, iTopY);
			iTopY++;
		}
		
		// draw vertical lines
		int iLeftX = (int) Math.ceil(leftx);
		while (iLeftX < rightx) {
			canvas.line(iLeftX, topy, iLeftX, bottomy);
			iLeftX++;
		}
		
		canvas.noStroke();
	}
}
