package org.crusty.wurrums.levels;

import org.crusty.wurrums.entities.Floater;
import org.crusty.wurrums.entities.Worm;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Random;

import org.crusty.engine.CrustyEngine;
import org.crusty.engine.Screen;
import org.crusty.engine.SoundManager;
import org.crusty.engine.entity.RootEntity;
import org.crusty.engine.sprite.Sprite;
import org.crusty.engine.sprite.SpriteManager;
import org.crusty.math.Vec2;

public abstract class TerrainLevel extends Screen {
	
	/** Full background collision Image */
	BufferedImage background;
	/** Solid parts of background that can't be destroyed */
	BufferedImage solidbackground;
	Color colour = new Color(255, 255, 155, 255);
	TerrainLevel nextScreen;
	long lastSpawned = 0;
	private long spawnFloaterTimer = 4000;
	
	public TerrainLevel(CrustyEngine engine, TerrainLevel nextScreen) {
		super(engine);
		
//		this.spriteName = spriteName;
//		this.wormPos = wormPos;
//		this.flagPos = flagPos;
		this.nextScreen = nextScreen;
//		this.entitiesToAdd = entitiesToAdd;
	}
	
	@Override
	public void draw(Graphics2D g) {
//		// Clear
//		g.setColor(Color.BLACK);
//		g.fillRect(0, 0, CrustyEngine.width, CrustyEngine.height);
		
		super.draw(g);
		
//		g.setColor(Color.WHITE);
//		g.drawString("Level 1", 100, 100);
	}
	
	public void setCurrentScreen(Screen s) {
		super.setCurrentScreen(s);
		if (s instanceof TerrainLevel)
			((TerrainLevel) s).reset();
	}

	@Override
	public void logic(long dt) {
		super.logic(dt);
		
//		if (CrustyEngine.keys[KeyEvent.VK_P]) {
//			// Save image
//			File file = new File("level.png");
//			try {
//				ImageIO.write(background, "png", file);
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
//		}
//		
//		if (CrustyEngine.keys[KeyEvent.VK_U]) { 
//			this.setCurrentScreen(this.nextScreen);
//			try {
//				Thread.sleep(500);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
//		}
		
		if (CrustyEngine.currentTimeMillis() - lastSpawned > spawnFloaterTimer ) {
//			System.out.println("Spawning Floater.");
			lastSpawned = CrustyEngine.currentTimeMillis();
			Random r = new Random();
			Sprite s = SpriteManager.getSprite("img/floaters/f" + Integer.toString(r.nextInt(3) + 1) + ".png");
			addEntity(new Floater(new Sprite[] { s }, 50, 50));
		}
		
		for (RootEntity f : this.getEntities()) {
			if (f instanceof Floater) {
				if (((Floater) f).markedForDeletion) {
					entities.remove(f);
//					System.out.println("Deleted");
				}
			}
		}
	}

	@Override
	public void keyTyped(KeyEvent e) {
		
	}
	
	public abstract Worm getWorm();
	
	public abstract void reset();
	
	public void mousePressed(MouseEvent e) {
		super.mousePressed(e);
//		if (e.getButton() == MouseEvent.BUTTON3) {
//			Graphics2D g = (Graphics2D) background.getGraphics();
//			g.setColor(colour);
//			int rad = 20;
//			g.fillOval(e.getX() - rad, e.getY() - rad, rad*2, rad*2);
//			
//			// Add texture to perlinNoise
//			Sprite texture = SpriteManager.getSprite("img/backgrounds/back1.bmp");
//			
//			AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_IN, 1);
////			Graphics2D g = (Graphics2D) perlinNoise.getGraphics();
//			Composite old = g.getComposite();
//			g.setComposite(ac);
//			// Tile texture
//			for (int y = 0; y <= background.getHeight(); y += texture.getHeight()) {
//				for (int x = 0; x <= background.getWidth(); x += texture.getWidth()) {
//					g.drawImage(texture.images[0], x, y, null);
//				}
//			}
//			System.out.println("Composite: " + old);
//			g.setComposite(old);
//			
//		} else if (e.getButton() == MouseEvent.BUTTON1) {
//			Graphics2D g = (Graphics2D) background.getGraphics();
//			Composite old = g.getComposite();
//			
//			// Make hole
//			g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, 1));
//			g.setColor(Color.BLACK);
//			int rad = 20;
//			g.fillOval((int) e.getX() - rad, (int) e.getY() - rad, rad*2, rad*2);
//			
////			Graphics2D g = (Graphics2D) perlinNoise.getGraphics();
////			g.setColor(colour);
////			if (CrustyEngine.keys[KeyEvent.VK_L]) {
////				g.drawLine(e.getX() - 20, e.getY(), e.getX() + 20, e.getY());
////			} else {
////				int rad = 50;
////				g.fillOval(e.getX() - rad, e.getY() - rad, rad*2, rad*2);
////			}
//		}
	}

	public Screen getNextScreen() {
		return nextScreen;
	}

	public BufferedImage getBackground() {
		return background;
	}

	public void createHole(double x, double y, int rad, Worm worm) {
		Graphics2D g = (Graphics2D) background.getGraphics();
		Composite old = g.getComposite();
		
		// Make hole where gun shot
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, 1));
		g.setColor(Color.BLACK);
		g.fillOval((int) x - rad, (int) y - rad, rad*2, rad*2);
		
		// Make line round hole
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, 1));
		rad = 23;
		g.setColor(Color.WHITE);
		g.fillOval((int) x - rad, (int) y - rad, rad*2, rad*2);
		rad = 21;
		g.setColor(Color.BLACK);
		g.fillOval((int) x - rad, (int) y - rad, rad*2, rad*2);

		g.setComposite(old);
		
		// Draw over solid background
		g.drawImage(solidbackground, 0, 0, null);
		
		if (new Vec2(x, y).sub(worm.pos).length() < rad) {
			worm.kill();
		}
		
		SoundManager.playSound("sounds/explosion.wav");
	}

	public boolean isFree(int x, int y) {
		int c = background.getRGB(x, y);
		int  alpha = (c & 0xff000000) >> 24;
//		int  red   = (c & 0x00ff0000) >> 16;
//		int  green = (c & 0x0000ff00) >> 8;
//		int  blue  = (c & 0x000000ff);
		if (alpha == 0)
			return true;
		else
			return false;
	}
	
	public boolean isFree(int x, int y, int x2, int y2) {
		
		Vec2 p1 = new Vec2(x, y);
		Vec2 p2 = new Vec2(x2, y2);
		
		Vec2 vec = p2.sub(p1);
		vec = vec.normalise();
		
		for (; p1.sub(p2).length() > 2 ; p1.x += vec.x, p1.y += vec.y) {
			if (!isFree((int) p1.x, (int) p1.y))
				return false;
		}
		return true;
	}

	public int getHeight() {
		return background.getHeight();
	}
	
	public int getWidth() {
		return background.getWidth();
	}

	public void drawBloodSplat(double x, double y) {
		Graphics2D g = (Graphics2D) background.getGraphics();
		Composite old = g.getComposite();
		
//		// Make hole where gun shot
//		g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, 1));
//		g.setColor(Color.BLACK);
//		g.fillOval((int) x - rad, (int) y - rad, rad*2, rad*2);
		
		// Make line round hole
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
//		rad = 23;
//		g.setColor(Color.WHITE);
//		g.fillOval((int) x - rad, (int) y - rad, rad*2, rad*2);
//		g.drawImage(SpriteManager.getSprite("img/otherEntities/bloodsplat.png").images[0], (int) x - 25, (int) y - 25, null);
		
		Sprite bloodsplat = SpriteManager.getSprite("img/otherEntities/bloodsplat.png");
		BufferedImage currentImage = bloodsplat.images[0];
		double scale = 2;
	
		int x1 = 0;
		int y1 = 0;
		int x2 = bloodsplat.getWidth();
		int y2 = bloodsplat.getHeight();
		
		int scaleBorderx = (int) (bloodsplat.getWidth() * (scale - 1)), 
		scaleBordery = (int) (bloodsplat.getHeight() * (scale - 1));
	
		g.drawImage(currentImage, 	(int) (x - 25) - scaleBorderx, // Destination
									(int) (y - 25) - scaleBordery, 
									(int) (x - 25 + bloodsplat.getWidth()) + scaleBorderx, 
									(int) (y - 25 + bloodsplat.getHeight()) + scaleBordery, 
									x1, // Source
									y1,
									x2, 
									y2, 
									null);
		
		g.setComposite(old);
	}

	public void createLand(int x, int y, int rad, Worm worm) {
		BufferedImage buildLayer = new BufferedImage(	background.getWidth(), 
														background.getHeight(), 
														BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = (Graphics2D) buildLayer.getGraphics();
		g.setColor(colour);
		rad -= 2;
		g.fillOval(x - rad, y - rad, rad*2, rad*2);
		rad += 2;
		
		// Add texture to perlinNoise
		Sprite texture = SpriteManager.getSprite("img/backgrounds/newterrain.bmp");
		
		AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_IN, 1);
		Composite old = g.getComposite();
		g.setComposite(ac);
		
		// Tile texture
		for (int y1 = 0; y1 <= background.getHeight(); y1 += texture.getHeight()) {
			for (int x1 = 0; x1 <= background.getWidth(); x1 += texture.getWidth()) {
				g.drawImage(texture.images[0], x1, y1, null);
			}
		}
		
//		g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, 1));
		
//		g.setColor(Color.WHITE);
//		g.fillOval(x - rad, y - rad, rad*2, rad*2);
		
		g.setComposite(old);
		
		// Draw layer on background
		Graphics2D g2 = (Graphics2D) background.getGraphics();
		
		old = g2.getComposite();
		g2.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, 1));
		
		g2.drawImage(buildLayer, 0, 0, null);
		
		g2.setComposite(old);
		
		// Draw over solid background
		g2.drawImage(solidbackground, 0, 0, null);
		
		SoundManager.playSound("sounds/createland.wav");
		
		if (new Vec2(x, y).sub(worm.pos).length() < rad) {
			worm.kill();
		}
	}

}
