define([
	"dojo/_base/declare", // declare
	"dojo/dom-class", // domClass.add
	"dojo/dom-geometry", // domGeometry.contentBox
	"dojo/dom-style", // domStyle.style
	"./StackContainer",
	"./utils", // marginBox2contextBox, layoutChildren
	"../registry",
	"../_TemplatedMixin",
	"dojo/text!./templates/TabContainer.html"
], function(declare, domClass, domGeometry, domStyle, StackContainer, layoutUtils, registry, _TemplatedMixin, template){

	// module:
	//		dijit/layout/_TabContainerBase

	return declare("dijit.layout._TabContainerBase", [StackContainer, _TemplatedMixin], {
		// summary:
		//		Abstract base class for TabContainer.   Must define _makeController() to instantiate
		//		and return the widget that displays the tab labels
		// description:
		//		A TabContainer is a container that has multiple panes, but shows only
		//		one pane at a time.  There are a set of tabs corresponding to each pane,
		//		where each tab has the name (aka title) of the pane, and optionally a close button.

		// tabPosition: String
		//		Defines where tabs go relative to tab content.
		//		"top", "bottom", "left-h", "right-h"
		tabPosition: "top",

		baseClass: "dijitTabContainer",

		// tabStrip: [const] Boolean
		//		Defines whether the tablist gets an extra class for layouting, putting a border/shading
		//		around the set of tabs.   Not supported by claro theme.
		tabStrip: false,

		// nested: [const] Boolean
		//		If true, use styling for a TabContainer nested inside another TabContainer.
		//		For tundra etc., makes tabs look like links, and hides the outer
		//		border since the outer TabContainer already has a border.
		nested: false,

		templateString: template,

		postMixInProperties: function(){
			// set class name according to tab position, ex: dijitTabContainerTop
			this.baseClass += this.tabPosition.charAt(0).toUpperCase() + this.tabPosition.substr(1).replace(/-.*/, "");

			this.srcNodeRef && domStyle.set(this.srcNodeRef, "visibility", "hidden");

			this.inherited(arguments);
		},

		buildRendering: function(){
			this.inherited(arguments);

			// Create the tab list that will have a tab (a.k.a. tab button) for each tab panel
			this.tablist = this._makeController(this.tablistNode);

			if(!this.doLayout){
				domClass.add(this.domNode, "dijitTabContainerNoLayout");
			}

			if(this.nested){
				/* workaround IE's lack of support for "a > b" selectors by
				 * tagging each node in the template.
				 */
				domClass.add(this.domNode, "dijitTabContainerNested");
				domClass.add(this.tablist.containerNode, "dijitTabContainerTabListNested");
				domClass.add(this.tablistSpacer, "dijitTabContainerSpacerNested");
				domClass.add(this.containerNode, "dijitTabPaneWrapperNested");
			}else{
				domClass.add(this.domNode, "tabStrip-" + (this.tabStrip ? "enabled" : "disabled"));
			}
		},

		_setupChild: function(/*dijit/_WidgetBase*/ tab){
			// Overrides StackContainer._setupChild().
			domClass.add(tab.domNode, "dijitTabPane");
			this.inherited(arguments);
		},

		startup: function(){
			if(this._started){
				return;
			}

			// wire up the tablist and its tabs
			this.tablist.startup();

			this.inherited(arguments);
		},

		layout: function(){
			// Overrides StackContainer.layout().
			// Configure the content pane to take up all the space except for where the tabs are

			if(!this._contentBox || typeof(this._contentBox.l) == "undefined"){
				return;
			}

			var sc = this.selectedChildWidget;

			if(this.doLayout){
				// position and size the titles and the container node
				var titleAlign = this.tabPosition.replace(/-h/, "");
				this.tablist.region = titleAlign;
				var children = [this.tablist, {
					domNode: this.tablistSpacer,
					region: titleAlign
				}, {
					domNode: this.containerNode,
					region: "center"
				}];
				layoutUtils.layoutChildren(this.domNode, this._contentBox, children);

				// Compute size to make each of my children.
				// children[2] is the margin-box size of this.containerNode, set by layoutChildren() call above
				this._containerContentBox = layoutUtils.marginBox2contentBox(this.containerNode, children[2]);

				if(sc && sc.resize){
					sc.resize(this._containerContentBox);
				}
			}else{
				// just layout the tab controller, so it can position left/right buttons etc.
				if(this.tablist.resize){
					//make the tabs zero width so that they don't interfere with width calc, then reset
					var s = this.tablist.domNode.style;
					s.width = "0";
					var width = domGeometry.getContentBox(this.domNode).w;
					s.width = "";
					this.tablist.resize({w: width});
				}

				// and call resize() on the selected pane just to tell it that it's been made visible
				if(sc && sc.resize){
					sc.resize();
				}
			}
		},

		destroy: function(preserveDom){
			if(this.tablist){
				this.tablist.destroy(preserveDom);
			}
			this.inherited(arguments);
		},

		selectChild: function(/*dijit/_WidgetBase|String*/ page, /*Boolean*/ animate){
			// Override _StackContainer.selectChild() so the page's focus isn't left in a strange state.

			if(this._focused){
				// Focus must be inside the currently selected tab,
				// or on the currently selected tab label.
				page = registry.byId(page);
				this.tablist.pane2button(page.id).focus();
			}
			return this.inherited(arguments);
		}
	});
});
