ig.module(
	'impact.system'
)
.requires(
	'impact.timer',
	'impact.image'
)
.defines(function(){

ig.System = ig.Class.extend({
	fps: 30,
	width: 320,
	height: 240,
	realWidth: 320,
	realHeight: 240,
	scale: 1,
	
	tick: 0,
	intervalId: 0,
	newGameClass: null,
	running: false,
	
	delegate: null,
	clock: null,
	canvas: null,
	context: null,
	
	smoothPositioning: true,

	hidden: '',
	visibilityChange: '',
	
	init: function( canvasId, fps, width, height, scale ) {
		this.fps = fps;
		
		this.width = width;
		this.height = height;
		this.scale = scale;
		
		this.realWidth = width * scale;
		this.realHeight = height * scale;
		
		this.clock = new ig.Timer();
		
		this.canvas = ig.$(canvasId);
		this.canvas.width = this.realWidth;
		this.canvas.height = this.realHeight;
		this.context = this.canvas.getContext('2d');

		if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support 
			this.hidden = "hidden";
			this.visibilityChange = "visibilitychange";
		} else if (typeof document.mozHidden !== "undefined") {
			this.hidden = "mozHidden";
			this.visibilityChange = "mozvisibilitychange";
		} else if (typeof document.msHidden !== "undefined") {
			this.hidden = "msHidden";
			this.visibilityChange = "msvisibilitychange";
		} else if (typeof document.webkitHidden !== "undefined") {
			this.hidden = "webkitHidden";
			this.visibilityChange = "webkitvisibilitychange";
		}
		document.addEventListener(this.visibilityChange, this.handleVisibilityChange.bind(this), false);
	},
	
	
	setGame: function( gameClass ) {
		if( this.running ) {
			this.newGameClass = gameClass;
		}
		else {
			this.setGameNow( gameClass );
		}
	},
	
	
	setGameNow: function( gameClass ) {
		ig.game = new (gameClass)();	
		ig.system.setDelegate( ig.game );
	},
	
	
	setDelegate: function( object ) {
		if( typeof(object.run) == 'function' ) {
			this.delegate = object;
			this.startRunLoop();
		} else {
			throw( 'System.setDelegate: No run() function in object' );
		}
	},
	
	
	stopRunLoop: function() {
		clearInterval( this.intervalId );
		this.running = false;
	},
	
	
	startRunLoop: function() {
		this.stopRunLoop();
		this.intervalId = setInterval( this.run.bind(this), 1000 / this.fps );
		this.running = true;
	},
	
	
	clear: function( color ) {
		this.context.fillStyle = color;
		this.context.fillRect( 0, 0, this.realWidth, this.realHeight );
	},

	handleVisibilityChange: function( event ) {
		// console.log("VISIBILITY HIDDEN: " + document[this.hidden]);
		if (document[this.hidden]) {
			if (this.running) {
				this.stopRunLoop();
				ig.music.pause();
			}
		} else {
			if (!this.running) {
				this.startRunLoop();
				ig.music.playTrack(ig.music.currentIndex);
			}
		}
	},	
	
	run: function() {
		ig.Timer.step();
		this.tick = this.clock.tick();
		
		this.delegate.run();
		ig.input.clearPressed();
		
		if( this.newGameClass ) {
			this.setGameNow( this.newGameClass );
			this.newGameClass = null;
		}
		
		//
		if (this._fadeIn)
		{
			var t = Date.now() - this._endTime;
			var alpha = 1;
			if( t < this._fadeToWhiteTime ) {
				alpha = t.map( 0, this._fadeToWhiteTime, 0, 1);
			}
			else {
				if (this._deferredSetGame)
				{
					ig.game.hide();
					
					this.setGame( this._deferredSetGame );
					
					this._deferredSetGame = null;
				}
				
				this._fadeIn = false;
				this._fadeOut = true;
				this._endTime = Date.now();
			}
			
			ig.system.context.fillStyle = 'rgba(' + this._fadeColor + ','+alpha+')';
			ig.system.context.fillRect( 0, 0, ig.system.realWidth, ig.system.realHeight );
		}
		else if (this._fadeOut)
		{
			var t = Date.now() - this._endTime;
			var alpha = 1;
			if( t < this._fadeToGameTime ) {
				alpha = t.map( 0, this._fadeToGameTime, 1, 0);
				
				ig.system.context.fillStyle = 'rgba(' + this._fadeColor + ','+alpha+')';
				ig.system.context.fillRect( 0, 0, ig.system.realWidth, ig.system.realHeight );
			}
			else {
				this._fadeOut = false;
			}
		}
	},
	
	
	getDrawPos: function( p ) {
		return this.smoothPositioning ? (p * this.scale).round() : p.round() * this.scale;
	},
	
	//
	_deferredSetGame: null,
	_fadeIn: false,
	_fadeOut: false,
	_fadeColor: '255,255,255',
	_endTime: 0,
	_fadeToWhiteTime: 300,
	_fadeToGameTime: 700,
	
	switchGame: function(game)
	{
		if (this._deferredSetGame)
			return;
			
		this._endTime = Date.now();
		this._deferredSetGame = game;
		this._fadeIn = true;
	},
});

});