//Add this file first to create the engine "namespace"...

var Engine = {}

Engine.InitEngine = function(container, pixiSettings)
{
	var type = "WebGL";
    if(!PIXI.utils.isWebGLSupported()) type = "canvas";

	PIXI.utils.sayHello(type);

	this.Pixi = new PIXI.Application(pixiSettings);

	PIXI.settings.MIPMAP_TEXTURES = false;

	EngineSettings.Pixi = this.Pixi;

	document.getElementById("gameContainer").appendChild(EngineSettings.Pixi.view);

	Engine.EnterFrameManagerInstance = new Engine.EnterFrameManager();
	Engine.DialogManagerInstance = new Engine.DialogManager();
	Engine.GraphicFactoryInstance = new Engine.GraphicFactory();
	Engine.SoundPlayerInstance = new Engine.SoundPlayer();
	Engine.SceneModeController = new Engine.SceneModeController();
	
	Engine.Drawable.fastRenderMode = false;

	this.rootDrawable = new Engine.Drawable();
	this.rootDrawable.onStage = true;
	this.Pixi.stage.addChild(this.rootDrawable);

	Engine.Mouse = new Engine.GlobalMouse();

}

Engine.GlobalMouse = class
{
	constructor()
	{
		Engine.EnterFrameManagerInstance.add(this, this.update);
		this.position = new Vector2(0, 0);
		this.mouseButtonDown = [false, false, false];

		EngineSettings.Pixi.renderer.plugins.interaction.on( 'pointerdown', (event) => { this.mouseDown(event); } );
		EngineSettings.Pixi.renderer.plugins.interaction.on( 'pointerup', (event) => { this.mouseUp(event); } );
		EngineSettings.Pixi.renderer.plugins.interaction.on( 'pointermove', (event) => { this.mouseMove(event); } );
		EngineSettings.Pixi.view.addEventListener('wheel', (event) => { this.mouseWheel(event); return false; }, false);

		this.events = EngineSettings.Pixi.renderer.plugins.interaction;

		this.eventHandlers = {};
		this.eventHandlers["mousedown"] = new Map();
		this.eventHandlers["mouseup"] = new Map();
		this.eventHandlers["mousewheel"] = new Map();
		this.eventHandlers["mousemove"] = new Map();
		this.eventHandlers["mouseflick"] = new Map();
		this.eventHandlers["mouseclick"] = new Map(); //TODO IMPLEMENT THIS!

		// so we dont remove on the same frame
		this.toRemove = {};

		EngineSettings.Pixi.view.addEventListener('mouseout', (event) => { this.viewMouseOut(event); return false; }, false);
		this.container = document.getElementById("gameContainer");
		this.container.style.position = "relative";
		window.addEventListener('mousedown', (event) => { this.windowMouseDown(event); return false; }, false);
	}


	removeEventListener(eventName, obj, immediate)
	{
		if (immediate === undefined) immediate = false;

		if (!immediate)
		{
			if (this.toRemove[eventName] === undefined) this.toRemove[eventName] = [];
			if (this.toRemove[eventName].indexOf(obj) == -1)
			{
				this.toRemove[eventName].push(obj);
			}
		}
		else
		{
			this.eventHandlers[eventName].delete(obj);
		}
	}

	addEventListener(eventName, obj, func)
	{
		if (func === undefined){
			Debug.Log("Func passed in as undefined to mouse event listener!");
		}
		
		if (this.toRemove[eventName] !== undefined)
		{
			var index = this.toRemove[eventName].indexOf(obj);
			if (index != -1)
			{
				this.toRemove[eventName].splice(index, 1);
			}
		}

		this.eventHandlers[eventName].set(obj, func);
	}

	fireEvent(eventName, data)
	{
		var eventFunctions = this.eventHandlers[eventName];
		if (eventFunctions !== undefined)
		{
			for (let obj of eventFunctions.keys())
	        {
	        	var func = eventFunctions.get(obj);
	            func.call(obj, data);
	        }
    	}
    	
		this.removeEvents();
	}

	mouseWheel(event)
	{
		event.preventDefault();
		//console.log(event);
		
		event.velocity = 0;
		if (event.deltaY > 0) event.velocity = 1;
		if (event.deltaY < 0) event.velocity = -1;
		if (event.velocity == 0) return;

		this.fireEvent("mousewheel", event.velocity);
	}

	mouseDown(event)
	{
		this.position.x = event.data.global.x;
		this.position.y = event.data.global.y;
		this.mouseButtonDown[0] = true;
		this.mouseButtonDown[event.data.originalEvent.which-1] = true;
		this.fireEvent("mousedown", this.position);
	}

	mouseUp(event)
	{
		this.mouseButtonDown[0] = false;
		if (event.data && event.data.originalEvent)
		{
			this.mouseButtonDown[event.data.originalEvent.which-1] = false;
		}
		this.fireEvent("mouseup", this.position);
	}

	mouseMove(event)
	{
		this.position.x = event.data.global.x;
		this.position.y = event.data.global.y;
		this.fireEvent("mousemove", this.position);
	}

	update(timeElapsed)
	{
		/*
		var mouseData = Engine.Pixi.renderer.plugins.interaction.mouse;
		this.position.x = mouseData.global.x;
		this.position.y = mouseData.global.y;
		*/

		if (Object.keys(this.toRemove).length > 0)
		{
			this.removeEvents();
		}
	}

	removeEvents()
	{
		for (var key in this.toRemove)
		{
			for (var o of this.toRemove[key])
			{
				this.eventHandlers[key].delete(o);
			}
			delete this.toRemove[key];
		}
	}

	viewMouseOut(event)
	{
		if (this.mouseButtonDown[0])
		{
			this.mouseUp(event);
		}
	}

	windowMouseDown(event)
	{
		var containerRect = this.container.getBoundingClientRect();

		// if clicked on game screen
		if (event.x >= containerRect.left && event.x < containerRect.right && event.y >= containerRect.top && event.y < containerRect.bottom)
		{
			if (!document.hasFocus())
	        {
	        	window.focus();
	        }
	        //TODO ONEDAY
       		//KeyboardManager.enable();
		}
		else
		{
       		//KeyboardManager.disable();
		}
	}
}