package rpgEngine.Logic.Game;

import java.util.List;
import java.util.Random;
import java.awt.event.KeyEvent;
import rpgEngine.Data.Abstract.Game;
import rpgEngine.Data.Abstract.Enemy.EnemyParty;
import rpgEngine.Data.Abstract.NPC.NPC;
import rpgEngine.Data.Abstract.World.CharacterAvatar;
import rpgEngine.Data.Abstract.World.Door;
import rpgEngine.Data.Abstract.World.Map;
import rpgEngine.Data.Abstract.World.MapCell;
import rpgEngine.Data.Raw.Graphics.CharacterSet;
import rpgEngine.Resources.MapPool;
import rpgEngine.UI.MainFrame;


public class PlayerMover {
	private MainFrame mainFrame;
	private Game game;
	private MapCell currentCell;
	private MapCell destCell;
	
	public PlayerMover(Game g, MainFrame mf) {
		game = g;
		currentCell = null;
		destCell = null;
		mainFrame = mf;
	}
	
	
	public void movePlayer(Integer keyCode) {
		Boolean destCellHasDoor = false;
		NPC npc = null;
		PlayerNPCActivater pna = null;
		Boolean varValue = false;
		Boolean varReq = false;
		Integer varID = -1;
		Boolean noNPC = true;
		
		if(game == null) {
			return;
		}
		
		//Determine cells involved with move
		determineCells(keyCode);
		
		//If destination cell does not exist, end
		if(destCell == null) {
			return;
		}
		
		//Determine if destination cell has a door
		if(destCell.getDoor() != null) {
			destCellHasDoor = true;
		}
		else {
			destCellHasDoor = false;
		}
		
		//Determine if destination cell has an NPC
		if(destCell.getNPC() != null) {
			npc = (NPC) destCell.getNPC();
			noNPC = false;
			
			//test to see if npc is showable
			if(npc.getHasOnlyShowCriteria()) {
				varID = npc.getOnlyShowVariable();
				varReq = npc.getOnlyShowVariableValue();
				varValue = game.getVariable(varID);
				
				if(varValue != varReq) {
					npc = null;
					noNPC = true;
				}
			}
			
			if(npc != null) {
				pna = new PlayerNPCActivater(game,npc);
				pna.activateNPC(mainFrame);
			}
		}
		
		if (noNPC) {
			if(isAbleToMakeMove()) {
				makeMove();
				
				if(destCellHasDoor) {
					useDoor();
				}
				else {
					if(testForMonsterFight()) {
						fightMonsters();
					}
				}
			}
		}
		
		changePlayerStep(keyCode);
	}
	
	
	private void fightMonsters() {
		List<EnemyParty> parties = game.getActiveMap().getEnemyParties();
		EnemyParty party = null;
		Random random = new Random();
		Integer partyIndex = 0;
		
		partyIndex = random.nextInt(parties.size());
		
		party = parties.get(partyIndex).createCopy();
		
		game.setActiveEnemyParty(party);
		
		mainFrame.showScreen(MainFrame.PANEL_BATTLE);
	}
	
	
	private Boolean testForMonsterFight() {
		Boolean result = false;
		Double random = 0.0;
		
		if(game.getActiveMap().getEnemyParties().size() == 0) {
			return result;
		}
		
		random = Math.random();
		
		if(random > 0.97) {
			result = true;
		}
		
		return result;
	}
	
	
	private void useDoor() {
		Map newMap = null;
		Door door = null;
		CharacterAvatar c = null;
		
		c = destCell.getCharacter();
		door = destCell.getDoor();
		destCell.setCharacter(null);
		
		newMap = MapPool.getInstance().getPoolItem(door.getMapID());
		
		if(newMap == null) {
			return;
		}
		
		destCell = newMap.getRows().get(door.getY()).get(door.getX());
		destCell.setCharacter(c);
		game.setActiveMap(newMap);
		
		//Change Music If necessary
		MusicPlayer.getInstance().changeMusicBasedOnScreen(mainFrame);
	}
	
	
	private void determineCells(Integer keyCode) {
		int sx = 0;
		int sy = 0;
		int dx = 0;
		int dy = 0;
		
		currentCell = null;
		destCell = null;
		
		currentCell = game.getActiveMap().findCharacter(game.getParty().get(0));
		
		sx = currentCell.getX();
		sy = currentCell.getY();
		
		if(keyCode == KeyEvent.VK_UP) {
			dx = sx;
			dy = sy - 1;
		}
		else if(keyCode == KeyEvent.VK_DOWN) {
			dx = sx;
			dy = sy + 1;
		}
		else if(keyCode == KeyEvent.VK_LEFT) {
			dx = sx - 1;
			dy = sy;
		}
		else if(keyCode == KeyEvent.VK_RIGHT) {
			dx = sx + 1;
			dy = sy;
		}		
		
		try {
			destCell = game.getActiveMap().getRows().get(dy).get(dx);
		}
		catch(Exception e) {
			destCell = null;
		}
	}
	
	
	private Boolean isAbleToMakeMove() {
		if(destCell.getCharacter() == null) {
			if(destCell.getTerrain().getWalkable() == false) {
				if(destCell.getTerrainObject() != null) {
					if(destCell.getTerrainObject().getWalkable() == false) {
						return false;
					}
					else {
						return true;
					}
				}
				else {
					return false;
				}
			}
			else {
				if(destCell.getTerrainObject() != null) {
					if(destCell.getTerrainObject().getWalkable() == false) {
						return false;
					}
					else {
						return true;
					}
				}
				else {
					return true;
				}
			}
		}
		else {
			return false;
		}
	}
	
	
	private void makeMove() {
		CharacterAvatar c = null;
		
		c = currentCell.getCharacter();
		
		currentCell.setCharacter(null);
		
		destCell.setCharacter(c);
	}
	
	
	private void changePlayerStep(Integer keyCode) {
		Integer currentImage = game.getParty().get(0).getCharacterPosition();
		Integer newImage = currentImage;
		
		if(keyCode == KeyEvent.VK_UP) {
			if(currentImage == CharacterSet.IMAGES_UP_0) {
				newImage = CharacterSet.IMAGES_UP_2;
			}
			else {
				newImage = CharacterSet.IMAGES_UP_0;
			}
		}
		else if(keyCode == KeyEvent.VK_DOWN) {
			if(currentImage == CharacterSet.IMAGES_DOWN_0) {
				newImage = CharacterSet.IMAGES_DOWN_2;
			}
			else {
				newImage = CharacterSet.IMAGES_DOWN_0;
			}
		}
		else if(keyCode == KeyEvent.VK_LEFT) {
			if(currentImage == CharacterSet.IMAGES_LEFT_0) {
				newImage = CharacterSet.IMAGES_LEFT_2;
			}
			else {
				newImage = CharacterSet.IMAGES_LEFT_0;
			}
		}
		else if(keyCode == KeyEvent.VK_RIGHT) {
			if(currentImage == CharacterSet.IMAGES_RIGHT_0) {
				newImage = CharacterSet.IMAGES_RIGHT_2;
			}
			else {
				newImage = CharacterSet.IMAGES_RIGHT_0;
			}
		}
		
		game.getParty().get(0).setCharacterPosition(newImage);
	}
	
}
