define(['jquery','ko','underscore','./observable_source','./renderer','../../logger/console-logger'],function($,ko,_,Source,renderer,consoleLogger){'use strict';var RemoteTemplateEngine,NativeTemplateEngine=ko.nativeTemplateEngine,sources={};RemoteTemplateEngine=function(){var engine=this,origUpdate=ko.bindingHandlers.template.update;this._rendersOutstanding=0;this._events=$(this);this._templatesRendered={};ko.bindingHandlers.template.update=function(element,valueAccessor,allBindings,viewModel,bindingContext){var options=ko.utils.peekObservable(valueAccessor()),templateName,isSync,updated;if(typeof options==='object'){if(options.templateEngine&&options.templateEngine!==engine){return origUpdate.apply(this,arguments);} if(!options.name){consoleLogger.error('Could not find template name',options);} templateName=options.name;}else if(typeof options==='string'){templateName=options;}else{consoleLogger.error('Could not build a template binding',options);} engine._trackRender(templateName);isSync=engine._hasTemplateLoaded(templateName);updated=origUpdate.apply(this,arguments);if(isSync){engine._releaseRender(templateName,'sync');} return updated;};};function createTemplateIdentifier(templateName){return templateName;} RemoteTemplateEngine.prototype=new NativeTemplateEngine;RemoteTemplateEngine.prototype.constructor=RemoteTemplateEngine;RemoteTemplateEngine.prototype._trackRender=function(templateName){var rendersForTemplate=this._templatesRendered[templateName]!==undefined?this._templatesRendered[templateName]:0;this._rendersOutstanding++;this._templatesRendered[templateName]=rendersForTemplate+1;this._resolveRenderWaits();};RemoteTemplateEngine.prototype._releaseRender=function(templateName){var rendersForTemplate=this._templatesRendered[templateName];this._rendersOutstanding--;this._templatesRendered[templateName]=rendersForTemplate-1;this._resolveRenderWaits();};RemoteTemplateEngine.prototype._resolveRenderWaits=function(){if(this._rendersOutstanding===0){this._events.triggerHandler('finishrender');}};RemoteTemplateEngine.prototype.waitForFinishRender=function(){var defer=$.Deferred();this._events.one('finishrender',defer.resolve);return defer.promise();};RemoteTemplateEngine.prototype._hasTemplateLoaded=function(templateName){return sources.hasOwnProperty(templateName);};RemoteTemplateEngine.prototype.makeTemplateSource=function(template,templateDocument,options,bindingContext){var engine=this,source,templateId;if(typeof template==='string'){templateId=createTemplateIdentifier(template);source=sources[templateId];if(!source){source=new Source(template);source.requestedBy=bindingContext.$data.name;sources[templateId]=source;consoleLogger.info('templateStartLoading',{template:templateId,component:bindingContext.$data.name});renderer.render(template).then(function(rendered){consoleLogger.info('templateLoadedFromServer',{template:templateId,component:bindingContext.$data.name});source.nodes(rendered);engine._releaseRender(templateId,'async');}).fail(function(){consoleLogger.error('templateLoadingFail',{template:templateId,component:bindingContext.$data.name});});} if(source.requestedBy!==bindingContext.$data.name){consoleLogger.info('templateLoadedFromCache',{template:templateId,component:bindingContext.$data.name});} return source;}else if(template.nodeType===1||template.nodeType===8){source=new ko.templateSources.anonymousTemplate(template);return source;} throw new Error('Unknown template type: '+template);};RemoteTemplateEngine.prototype.renderTemplateSource=function(templateSource){var nodes=templateSource.nodes();return ko.utils.cloneNodes(nodes);};RemoteTemplateEngine.prototype.renderTemplate=function(template,bindingContext,options,templateDocument){var templateSource=this.makeTemplateSource(template,templateDocument,options,bindingContext);return this.renderTemplateSource(templateSource);};return new RemoteTemplateEngine;});