package projectzombie;

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.io.File;
import java.io.IOException;
import java.util.Random;

import bdf.types.BdfReader;
import gl_engine.MathHelpers;
import mainloop.manager.MainloopManager;
import projectzombie.audio.AudioEngine;
import projectzombie.audio.AudioSources;
import projectzombie.display.DisplayStatsEventHandler;
import projectzombie.display.DisplayWindow;
import projectzombie.entity.EntityEventHandler;
import projectzombie.entity.player.EntityPlayer;
import projectzombie.init.Entities;
import projectzombie.init.ItemModifiers;
import projectzombie.init.Items;
import projectzombie.init.LayerGenerators;
import projectzombie.init.Recipes;
import projectzombie.init.Resources;
import projectzombie.init.Sounds;
import projectzombie.init.Tasks;
import projectzombie.init.Tiles;
import projectzombie.input.JoystickCallback;
import projectzombie.input.KeyCallback;
import projectzombie.mainloop.MainloopEventHandler;
import projectzombie.mainloop.MainloopHelpers;
import projectzombie.menu.Menu;
import projectzombie.menu.MenuMain;
import projectzombie.settings.Cheats;
import projectzombie.settings.Environment;
import projectzombie.settings.Settings;
import projectzombie.time.GameTimer;
import projectzombie.time.NoSleep;
import projectzombie.util.FileHelpers;
import projectzombie.worker.WorkerTasks;
import projectzombie.worker.WorkerLighting;
import projectzombie.world.World;
import projectzombie.world.chunk.ChunkEventHandler;

public class Main
{
	public static BdfReader bdf_saves;
	
	public static Clipboard clipboard;
	public static MainloopManager mainloop;
	public static DisplayWindow window;
	public static EntityPlayer player;
	public static World world;
	public static AudioEngine audio;
	public static Random rand = new Random();
	public static Menu menu;
	public static WorkerLighting workerLighting;
	public static WorkerTasks[] workerChunks;
	public static boolean game_paused = false;
	public static boolean running = true;
	public static int tickrate = 10;
	
	public static void main(String[] args) throws IOException
	{
		try
		{
			Environment.init(args);
			File global_dir = new File(Environment.gdir);
			
			// Make this directory if it doesn't exist
			if(!global_dir.isDirectory())
			{
				if(global_dir.exists()) {
					global_dir.delete();
				}
				
				global_dir.mkdirs();
			}
			
			Runtime runtime = Runtime.getRuntime();
			int cores = runtime.availableProcessors();
			
			clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
			
			workerLighting = new WorkerLighting();
			workerLighting.start();
			
			int workers = cores - 2;
			if(workers < 1) {
				workers = 1;
			}
			
			workerChunks = new WorkerTasks[workers];
			
			for(int i=0;i<workerChunks.length;i++) {
				workerChunks[i] = new WorkerTasks();
				workerChunks[i].start();
			}
			
			MathHelpers.init();
			Settings.init();
			Cheats.init(args);
			
			Items.init();
			ItemModifiers.init();
			Entities.init();
			Tasks.init();
			Tiles.init();
			LayerGenerators.init();
			Recipes.init();
			
			bdf_saves = FileHelpers.readBDF("./saves.bdf.gz");
			
			// Create the display
			window = new DisplayWindow();
			window.init();
			
			// Load the resources
			Resources.loadResources();
			
			// Initialize the sound engine
			audio = new AudioEngine();
			audio.init();
			
			// Initialise the sounds
			AudioSources.init();
			Sounds.init();
			
			// Initialize the gamepad
			JoystickCallback.JOYSTICK_CALLBACK.init();
			
			// Create the mainloop
			mainloop = new MainloopManager(MainloopEventHandler.MAINLOOP_EVENT_HANDLER);
			mainloop.register(DisplayStatsEventHandler.DISPLAY_STATS_EVENT_HANDLER);
			mainloop.register(MainloopEventHandler.MAINLOOP_EVENT_HANDLER);
			mainloop.register(EntityEventHandler.ENTITY_EVENT_HANDLER);
			mainloop.register(ChunkEventHandler.CHUNK_EVENT_HANDLER);
			mainloop.register(JoystickCallback.JOYSTICK_CALLBACK);
			mainloop.register(new MainloopHelpers());
			mainloop.register(new KeyCallback());
			mainloop.register(new GameTimer());
			mainloop.register(new NoSleep());
			mainloop.register(window);
			
			// Start the mainloop
			menu = new MenuMain();
			mainloop.start();
		}
		
		finally
		{
			// Kill the worker threads
			running = false;
		}
	}
}
