/*global define*/
define(
	[ 'config', 'util/dom', 'util/object', 'util/string', 'util/addpublishers', 'lib/reqwest' ],
	function ( config, domHelper, objectHelper, stringHelper, addPublishers, reqwest ) {
		function LocalisationModel () {
			if ( ! ( this instanceof LocalisationModel ) ) {
				return new LocalisationModel();
			}

			var self = this;

			var publishers = addPublishers( self, 'update', 'error' );
			
			var textElData = [ ];
			var texts = '';
			var currentLanguage = '';

			var animationFrameId = NaN;
			var languageWasLoaded = false;
			
			var linkOptions = { links: { newTab: true } };

			function setLanguage ( newLanguage ) {
				if ( newLanguage !== currentLanguage && newLanguage in config.availableLanguages ) {
					loadLanguage( newLanguage );
				}
			}

			function loadLanguage ( languageName ) {
				languageWasLoaded = false;

				reqwest( {
					url: config.language.dir + '/' + languageName + '.json',
					type: 'json',
					method: 'get',
					error: function ( err, one, two ) {
						// if this is the first language to load, that's really bad.
						languageWasLoaded = true;
						publishers.error.dispatch( 'I\'m really sorry. I failed to load the language file for ' + languageName + '. This is a serious error that makes the app very hard to use. Maybe you can try reloading?' );
					},
					success: function ( res ) {
						languageLoaded( languageName, res );
					}
				} );
			}

			function languageLoaded ( newLanguageName, newTexts ) {
				currentLanguage = newLanguageName;
				languageWasLoaded = true;
				texts = newTexts;
				resetAllTexts();
				updateAllTexts();
			}

			function updateAllTexts () {
				if ( languageWasLoaded ) {
					cancelAnimationFrame( animationFrameId );

					animationFrameId = requestAnimationFrame( function () {
						var item;
						var args;

						for ( var i = textElData.length - 1; i >= 0; i-- ) {
							item = textElData[i];
							
							if ( domHelper.isElement( item.el ) ) {
								if ( ! item.wasUpdated ) {
									if ( item.attribute === 'innerHTML' ) {
										item.el.innerHTML = stringHelper.markdownToHtml( getTextForKey( item.key, item.args ), linkOptions );
									} else {
										item.el[item.attribute] = getTextForKey( item.key, item.args );
									}
									
									item.wasUpdated = true;
								}
							} else {
								textElData.splice( i, 1 );
							}
						}

						publishers.update.dispatch();
					} );
				}
			}

			function resetAllTexts () {
				textElData.forEach( function ( item ) {
					item.wasUpdated = false;
				} );
			}

			function getTextForKey ( key, args ) {
				var result = '';

				try {
					result = objectHelper.getObjectByString( key, texts );
				} catch ( e ) {
					if ( languageWasLoaded ) {
						result = key
					}
				};

				if ( args && args.length ) {
					var regex;

					args.forEach( function ( arg, index ) {
						regex = new RegExp( '{\\$' + ( index + 1 ) + '}' );
						result = result.replace( regex, arg );
					} );
				}

				return result;
			}

			// http://mzl.la/1RDxjVO
			function getArgs ( args, firstIndex ) {
				firstIndex = firstIndex || 3;
				var result;

				if ( args.length > firstIndex ) {
					result = [ ];
				}

				for ( var i = firstIndex, len = args.length; i < len; i++ ) {
					result[result.length] = args[i];
				}

				return result;
			}

			function settingUpdated ( name, value ) {
				if ( name === 'language' && value !== currentLanguage ) {
					loadLanguage( value );
				}
			}

			function localizeText ( el, attribute, key ) {
				if ( el && attribute && key ) {
					textElData.push( { el: el, attribute: attribute, key: key, wasUpdated: false, args: getArgs( arguments ) } );
				} else {
					if ( typeof el === 'string' ) {
						return getTextForKey( el, getArgs( arguments, 1 ) );
					}
				}

				updateAllTexts();
			}

			self.setLanguage = setLanguage;
			self.localizeText = localizeText;
			self.settingUpdated = settingUpdated;
			self.randomNumber = ~~( Math.random() * 1000 );
		}

		LocalisationModel.sharedInstance = LocalisationModel();

		return LocalisationModel;
	}
);
@@ -3975,59 +3975,8 @@
 ed;%0A
-%09%09%09self.randomNumber = ~~( Math.random() * 1000 );%0A
 %09%09%7D%0A

remove debug code