dojo.provide("dojoX.widget.DynamicStackContainer");
dojo.require("dojo.html");
(function(){
	var substitute = function( /*String*/template, /*Object|Array*/
	map, /*Function?*/
	store,
	transform, /*Object?*/
	thisObject){
		thisObject = thisObject || dojo.global;
		transform = (!transform) ? function(v){
				return v;
			} : dojo.hitch(thisObject, transform);
		return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g, function(match, key, format){
			var value;
			if (store && store.isItem(map)) {
				value = store.getValue(map, key);
			}
			else {
				value = dojo.getObject(key, false, map); //store must support dot notation for dot props. FIXME
			}
			
			if (format) {
				value = dojo.getObject(format, false, thisObject).call(thisObject, value, key);
			}
			return (value = transform(value, key)) ? value.toString() : "";
		}); // string
	};
	
	dojo.declare("dojox.widget._DynamicStackContainer", null, {
		
		store:null, //data store to query. must provide store or data 
		data:null, //array of data to use for tabs. must be an array of objects, not just an array of strings!
		transform:null, //object that converts value via the dojo.string.substitute transofrm mechanism
		formatter:null, //object with methods that can be used via the dojo.string.substitute :format mechanism
		
		query: null, //readApi query
		queryOptions: null, //readApi queryOptions
		sort:null, //readApi sort
		
		titleAttribute:"label", //attribute of items to use as the title for each tab, default to label
		idAttribute:"id", //used to create the dynamic id of the child panes as id_${id}
		loadingMessage:"Loading...",
		noDataMessage:"No tabs available.",
		errorMessage:"Error loading tabs...",
		
		dojoTypeAttribute:"_dojoType", //the name of an attribute used in any dynamic children to indicate the dojoType of the widget
								       //this will be converted to dojoType at run time.
		
		_pending_requests: null,
		_childTemplate:null,
		_isLoaded: false,
		_isLoading: false,
		
		_cache:null,
		_paneType:null,
		
		
		constructor: function(){
			//summary: mix this class into a StackContainer, and you can then have DataTabContainer, DataStackContainer, DataAccordionContainer
			//description:
			//  provide either a store/query/queryOptions/sort set or provide a data array
			//  this will create a tab for each item, using the "titleAttribute" property
			//  as the name of the property on the item as the title.
			//  when the tab is displayed, the child of this container is created
			//  replacing ${foo} style variables in the template with properties
			//  of the item. If a store was provided, uses store.getValue(item, 'foo'), otherwise
			//  uses item['foo'] for the value. You may also provide a transform object
			//  and a formatter object for getting/modifying values from your items
			//  (see dojo.string.substitute for details of transform/formatter)
			// this will use the set of children that have dynamic="true" as the template, allowing
			// you to add static panes as well
			
		},
		
		
		postMixInProperties: function(){
			this._pending_requests = {};
			this._cache = [];
			this._paneType = (this instanceof dijit.layout.AccordionContainer) ? dijit.layout.AccordionPane : dijit.layout.ContentPane;
			var dynamicNodes = dojo.query("> [dynamic='true']", this.srcNodeRef).orphan();
			var tempNode =  dojo.html.set(dojo.doc.createElement('div'), dynamicNodes);
			this.contentString =(tempNode.innerHTML + "").replace(new RegExp(this.dojoTypeAttribute, 'gi'), "dojoType");
			this.inherited(arguments);
			
		},
		
		buildRendering: function(doInherited){
			// summary: create the content panes
			this.inherited(arguments);
			
			if (this.store) {
				this._fetch(0);
			}
			else {
				dojo.forEach(this.data, this._addItem, this);
			}
		},
		
		
		
		startup:function() {
			//summary: instantiate the currently selected tab's template
			if (this._isLoading) {
				this._pendingStartup = true;
				return;
			}
			//if we are still loading, then just wait until we are done. startup will be called after loading
			if (!this._isStarted) {
				this.inherited(arguments);
				if (this.selectedChildWidget) {
					this.createSelectedChildWidget(this.selectedChildWidget);
				}
				this._isStarted = true; //only call once
				this._pendingStartup = false;
			}
		},
		
		createSelectedChildWidget:function(selectedPane) {
			//summary: instantiate the selectedPane.  substitute the templateString parameters before we instantiate it.
			
			
			if (!selectedPane._isInitialized && selectedPane.isDynamic) {
				var item = selectedPane.tabContext;
				
				var templateString = substitute(this.contentString, item, this.store, this.transform, this.formatter);
				selectedPane.attr('content', templateString);
				
				selectedPane._isInitialized = true;
			}
			
		},
	
	
	selectChild:function(widget) {
		this.createSelectedChildWidget(widget);
		this.inherited(arguments);
	},
	
	showMessage:function(message) {
		//summary: TODO, show pretty messages about the status of the container.
		console.log("DynamicStackContainer.showMessage", message);
	},
	
	_fetch: function(start){
		start = start || 0;
		if(this.store && !this._pending_requests[start]){
			if(!this._isLoaded && !this._isLoading){
				this._isLoading = true;
				this.showMessage(this.loadingMessage);
			}
			this._pending_requests[start] = true;
			//console.log("fetch: ", start);
			try{
				this.store.fetch({
					start: start,
					//count: this.rowsPerPage,
					query: this.query,
					sort: this.sort,
					queryOptions: this.queryOptions,
					onBegin: dojo.hitch(this, "_onFetchBegin"),
					onComplete: dojo.hitch(this, "_onFetchComplete"),
					onError: dojo.hitch(this, "_onFetchError")
				});
			}catch(e){
				this._onFetchError(e);
			}
		}
	},
	
	_setQuery: function(query, queryOptions){
		this.query = query || this.query;
		this.queryOptions = queryOptions || this.queryOptions;		
	},

	_onFetchBegin: function(size, req){
		
	},

	_addItem:function(item, index) {
		//summary: actually creates the child content pane
		var contentPane = new this._paneType({title:
			item[this.titleAttribute] || "Title", tabContext:item, 
			isDynamic:true, 
			id:this.store ? (this.id + "_child_" + this.store.getValue(item, this.idAttribute)) + '_' + index : (this.id + "_child_" + item[this.idAttribute] + '_' + index)}
		);
		this.addChild(contentPane);
		
	},

	_onFetchComplete: function(items, req){
		if (this.data) {
			items = this.data.concat(items);
		}
		if(items && items.length > 0){
			dojo.forEach(items, function(item, idx){
				this._addItem(item, req.start+idx);
			}, this);
		}
		if(!this._isLoaded){
			this._isLoading = false;
			this._isLoaded = true;
			if(!items || !items.length){
				this.showMessage(this.noDataMessage);
			}else{
				this.showMessage();
			}
		}
		this._pending_requests[req.start] = false;
		this.onFetchComplete(items, req);
	},
	
	onFetchComplete:function(items, req) {
		if (this._pendingStartup) {
			this.startup();
		}
	},

	_onFetchError: function(err, req){
		console.error(err);
		if(!this._isLoaded){
			this._isLoading = false;
			this._isLoaded = true;
			this.showMessage(this.errorMessage);
		}
		this.onFetchError(err, req);
	},

	onFetchError: function(err, req){
	}
	});
	
	dojo.declare("dojox.widget.DynamicTabContainer", [dijit.layout.TabContainer, dojox.widget._DynamicStackContainer], {});
	dojo.declare("dojox.widget.DynamicStackContainer", [dijit.layout.StackContainer, dojox.widget._DynamicStackContainer], {});
	dojo.declare("dojox.widget.DynamicAccordionContainer", [dijit.layout.AccordionContainer, dojox.widget._DynamicStackContainer], {});
})();
