package com.rs.game.player.content.dungeoneering.rooms.puzzles;

import com.rs.game.Animation;
import com.rs.game.World;
import com.rs.game.WorldObject;
import com.rs.game.WorldTile;
import com.rs.game.player.Player;
import com.rs.game.player.Skills;
import com.rs.game.player.content.dungeoneering.rooms.PuzzleRoom;
import com.rs.game.tasks.WorldTask;
import com.rs.game.tasks.WorldTasksManager;

public class CrystalPuzzleRoom extends PuzzleRoom {

	private static final int ANIM_CHARGE_LODESTONE = 833;

	// Lodestone base location
	private static final int[] POS_BASE_LODESTONE = { 10, 1 };

	// Large crystal in the center
	private static final int[] POS_CENTER = { 7, 8 };

	// Direction for each color
	private static final int[][] POS_DELTA = { { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 1 }, };

	// Pressure plate location for each color
	private static final int[][] POS_PLATE = { { 2, 8 }, { 7, 13 }, { 12, 8 }, { 7, 3 }, };

	// Large center crystal lighting
	private static final int[] LARGE_CRYSTAL_OFF = { 49507, 49508, 49509, 54275, 34866 };
	private static final int[] LARGE_CRYSTAL_FLASH = { 49510, 49511, 49512, 54276, 35070 };
	private static final int[] LARGE_CRYSTAL_ON = { 49513, 49514, 49515, 54277, 35231 };

	// Tile lighting
	private static final int[] TILE_INACTIVE = { 49465, 49466, 49467, 54261, 34317 };
	private static final int[][] TILE_ACTIVE = { { 49468, 49469, 49470, 54262, 34319 }, { 49477, 49478, 49479, 54265, 34848 }, { 49486, 49487, 49488, 54268, 34856 }, { 49495, 49496, 49497, 54271, 34862 } };

	// Pressure plates
	// private static final int[] PLATE = { 52206, 52206, 52206, 54282, 35232 };

	// Active lodestone id's
	private static final int[][] LODESTONE_ACTIVE = { { 49474, 49475, 49476, 54264, 34847 }, { 49483, 49484, 49485, 54267, 34855 }, { 49492, 49493, 49494, 54270, 34861 }, { 49501, 49502, 49503, 54273, 34864 }, };

	// Inactive lodestone id's
	private static final int[][] LODESTONE_INACTIVE = { { 49471, 49472, 49473, 54263, 34320 }, { 49480, 49481, 49482, 54266, 34852 }, { 49489, 49490, 49491, 54269, 34860 }, { 49498, 49499, 49500, 54272, 34863 }, };

	private boolean[] active;
	private int[][] energyTile;
	private TileTask task;

	@Override
	public void openRoom() {
		manager.spawnRandomNPCS(reference);
		type = manager.getParty().getFloorType();
		active = new boolean[4];
		energyTile = new int[4][2];
		int activeCount = 0;
		for (int color = 0; color < 4; color++) {
			if (Math.random() > 0.66 && activeCount++ != 3) {
				resetPosition(color);
				World.spawnObject(new WorldObject(LODESTONE_ACTIVE[color][type], 10, 0, manager.getTile(reference, POS_BASE_LODESTONE[0] + color, POS_BASE_LODESTONE[1] + color)));
			} else {
				World.spawnObject(new WorldObject(LODESTONE_INACTIVE[color][type], 10, 0, manager.getTile(reference, POS_BASE_LODESTONE[0] + color, POS_BASE_LODESTONE[1] + color)));
			}
		}
		task = new TileTask();
		WorldTasksManager.schedule(task, 0, 0);
	}

	@Override
	public boolean processObjectClick1(Player p, WorldObject object) {
		for (int color = 0; color < 4; color++) {
			if (object.getId() == LODESTONE_INACTIVE[color][type]) {
				if (!hasRequirement(p, Skills.MAGIC)) {
					p.getPackets().sendGameMessage("You need a magic level of " + getRequirement(Skills.MAGIC) + " to power this lodestone.");
					return false;
				}
				giveXP(p, Skills.MAGIC);
				p.setNextAnimation(new Animation(ANIM_CHARGE_LODESTONE));
				p.lock(1);
				resetPosition(color);
				World.spawnObject(new WorldObject(LODESTONE_ACTIVE[color][type], 10, 0, manager.getTile(reference, POS_BASE_LODESTONE[0] + color, POS_BASE_LODESTONE[1] + color)));
				p.getPackets().sendGameMessage("You reach out and find the lodestone's power source. You spark it into life.");
				return false;
			}
		}
		return true;
	}

	private void resetPosition(int color) {
		active[color] = true;
		energyTile[color][0] = POS_PLATE[color][0] + POS_DELTA[color][0];
		energyTile[color][1] = POS_PLATE[color][1] + POS_DELTA[color][1];
		World.spawnObject(new WorldObject(TILE_ACTIVE[color][type], 22, 0, manager.getTile(reference, energyTile[color][0], energyTile[color][1])));
	}

	@Override
	public String getCompleteMessage() {
		return "You hear a click. All the doors in the room are now unlocked.";
	}

	public class TileTask extends WorldTask {

		@Override
		public void run() {
			synchronized (manager) {
				if (manager.isDestroyed()) {
					stop();
					return;
				}
				outer: for (int color = 0; color < 4; color++) {
					// Make sure it's actually active
					if (!active[color])
						continue;
					// ... and nobody is standing on it
					for (Player player : manager.getParty().getTeam()) {
						WorldTile last = player;
						if (player.getLastWorldTile() != null) {
							last = player.getLastWorldTile();
						}
						WorldTile tile = manager.getTile(reference, POS_PLATE[color][0], POS_PLATE[color][1]);
						if (tile == null)
							return;
						if (last.withinDistance(tile, 0)) {
							continue outer;
						}
					}

					// Remove current tile
					World.spawnObject(new WorldObject(TILE_INACTIVE[type], 22, 0, manager.getTile(reference, energyTile[color][0], energyTile[color][1])));

					// Rewind position if it's in the center
					if (energyTile[color][0] == POS_CENTER[0] && energyTile[color][1] == POS_CENTER[1]) {
						resetPosition(color);
					} else {
						// Actually move it
						energyTile[color][0] += POS_DELTA[color][0];
						energyTile[color][1] += POS_DELTA[color][1];
						World.spawnObject(new WorldObject(TILE_ACTIVE[color][type], 22, 0, manager.getTile(reference, energyTile[color][0], energyTile[color][1])));
					}
				}

				// Check if puzzle is complete
				boolean complete = true;
				boolean any = false;
				for (int color = 0; color < 4; color++) {
					if (energyTile[color][0] != POS_CENTER[0] || energyTile[color][1] != POS_CENTER[1]) {
						complete = false;
					} else {
						any = true;
					}
				}

				if (complete) {
					World.spawnObject(new WorldObject(LARGE_CRYSTAL_ON[type], 10, 0, manager.getTile(reference, POS_CENTER[0], POS_CENTER[1])));
					setComplete();
					stop();
					task = null;
				} else if (any) {
					World.spawnObject(new WorldObject(LARGE_CRYSTAL_FLASH[type], 10, 0, manager.getTile(reference, POS_CENTER[0], POS_CENTER[1])));
				} else {
					World.spawnObject(new WorldObject(LARGE_CRYSTAL_OFF[type], 10, 0, manager.getTile(reference, POS_CENTER[0], POS_CENTER[1])));
				}
			}
		}

	}

	@Override
	public void destroy() {
		if (task != null) {
			task.stop();
			task = null;
		}
	}

}
