var SLIDE_PUZZLE = window.SLIDE_PUZZLE || {};

SLIDE_PUZZLE.Stopwatch = function(tickMillis) {
	var self = this;
	
	this._tickMillis = tickMillis;
	this._startTime = null;
	this._intervalID = null;
	this._priorElapsed = 0;
	this._currentElapsed = 0;
	
	this._listeners = [];
	
	this.__defineGetter__("isRunning", function() {
		return self._intervalID !== null;
	});
	
	this.__defineGetter__("elapsedMillis", function() {
		return self._priorElapsed + self._currentElapsed;
	});
	
	function divideInt(a, b) {
		return Math.floor(a/b);
	}
	
	this.__defineGetter__("elapsedString", function() {
		var totalMillis = self._priorElapsed + self._currentElapsed;
		
		var seconds = divideInt(totalMillis, 1000) % 60;
		var minutes = divideInt(totalMillis, 60000) % 60;
		var hours = divideInt(totalMillis, 3600000);
		
		var showHours = hours > 0;
		var showMinutes = minutes > 0 || showHours;
		var fixMinutes = showHours;
		var fixSeconds = showMinutes;
		
		var hoursString;
		if (showHours) {
			hoursString = hours + ':';
		} else {
			hoursString = '';
		}
		
		var minutesString;
		if (showMinutes) {
			if (fixMinutes && minutes < 10) {
				minutesString = '0' + minutes + ':';
			} else {
				minutesString = minutes + ':';
			}
		} else {
			minutesString = '';
		}
		
		var secondsString;
		if (fixSeconds && seconds < 10) {
			secondsString = '0' + seconds;
		} else {
			secondsString = seconds.toString();
		}
		
		return hoursString + minutesString + secondsString;
	});
};

SLIDE_PUZZLE.Stopwatch.prototype.start = function() {
	if (!this.isRunning) {
		var self = this;
		
		function tick() {
			self._currentElapsed = window.performance.now() - self._startTime;
			self._dispatchTickEvent();
		}
		
		this._startTime = window.performance.now();
		this._intervalID = window.setInterval(tick, this._tickMillis);
	} else {
		throw new Error("can't start a started stopwatch");
	}
};

SLIDE_PUZZLE.Stopwatch.prototype.stop = function() {
	if (this.isRunning) {
		window.clearInterval(this._intervalID);
		this._intervalID = null;
		this._startTime = null;
		
		this._priorElapsed += this._currentElapsed;
		this._currentElapsed = 0;
	} else {
		throw new Error("can't stop a stopped stopwatch");
	}
};

SLIDE_PUZZLE.Stopwatch.prototype.reset = function() {
	if (!this.isRunning) {
		this._priorElapsed = 0;
		this._currentElapsed = 0;
		this._dispatchTickEvent();
	} else {
		throw new Error("can't reset a started stopwatch");
	}
};

SLIDE_PUZZLE.Stopwatch.prototype.addEventListener = function(type, listener) {
	if (type === 'tick') {
		this._listeners.push(listener);
	}
};

SLIDE_PUZZLE.Stopwatch.prototype._dispatchTickEvent = function() {
	var event = document.createEvent('CustomEvent');
	event.initCustomEvent('tick', false, false, null);
	for (var i = 0; i < this._listeners.length; i++) {
		this._listeners[i](event);
	}
}
