/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.PageContainer");

dojo.require("dojo.lang.func");
dojo.require("dojo.widget.*");
dojo.require("dojo.event.*");
dojo.require("dojo.html.selection");

dojo.widget.defineWidget("dojo.widget.PageContainer", dojo.widget.HtmlWidget, {
	// summary
	//	A container that has multiple children, but shows only
	//	one child at a time (like looking at the pages in a book one by one).
	//
	//	Publishes topics <widgetId>-addChild, <widgetId>-removeChild, and <widgetId>-selectChild
	//
	//	Can be base class for container, Wizard, Show, etc.

	isContainer: true,

	// doLayout: Boolean
	//  if true, change the size of my currently displayed child to match my size
	doLayout: true,

	templateString: "<div dojoAttachPoint='containerNode'></div>",

	// selectedChild: String
	//   id of the currently shown page
	selectedChild: "",

	fillInTemplate: function(args, frag) {
		// Copy style info from input node to output node
		var source = this.getFragNodeRef(frag);
		dojo.html.copyStyle(this.domNode, source);
		dojo.widget.PageContainer.superclass.fillInTemplate.apply(this, arguments);
	},

	postCreate: function(args, frag) {
		if(this.children.length){
			// Setup each page panel
			dojo.lang.forEach(this.children, this._setupChild, this);

			// Figure out which child to initially display
			var initialChild;
			if(this.selectedChild){
				this.selectChild(this.selectedChild);
			}else{
				for(var i=0; i<this.children.length; i++){
					if(this.children[i].selected){
						this.selectChild(this.children[i]);
						break;
					}
				}
				if(!this.selectedChildWidget){
					this.selectChild(this.children[0]);
				}
			}
		}
	},

	addChild: function(child){
		dojo.widget.PageContainer.superclass.addChild.apply(this, arguments);
		this._setupChild(child);

		// in case the tab labels have overflowed from one line to two lines
		this.onResized();

		// if this is the first child, then select it
		if(!this.selectedChildWidget){
			this.selectChild(child);
		}
	},

	_setupChild: function(/*Widget*/ page){
		// Summary: Add the given child to this page container

		page.hide();

		// since we are setting the width/height of the child elements, they need
		// to be position:relative, or IE has problems (See bug #2033)
		page.domNode.style.position="relative";

		// publish the addChild event for panes added via addChild(), and the original panes too
		dojo.event.topic.publish(this.widgetId+"-addChild", page);
	},

	removeChild: function(/*Widget*/ page){
		dojo.widget.PageContainer.superclass.removeChild.apply(this, arguments);

		// If we are being destroyed than don't run the code below (to select another page), because we are deleting
		// every page one by one
		if(this._beingDestroyed){ return; }

		// this will notify any tablists to remove a button; do this first because it may affect sizing
		dojo.event.topic.publish(this.widgetId+"-removeChild", page);

		// in case the tab labels now take up one line instead of two lines
		this.onResized();

		if (this.selectedChildWidget === page) {
			this.selectedChildWidget = undefined;
			if (this.children.length > 0) {
				this.selectChild(this.children[0], true);
			}
		}
	},

	selectChild: function(/*Widget*/ page, /*Widget*/ callingWidget){
		// summary
		//	Show the given widget (which must be one of my children)
		page = dojo.widget.byId(page);
		this.correspondingPageButton = callingWidget;

		// Deselect old page and select new one
		if(this.selectedChildWidget){
			this._hideChild(this.selectedChildWidget);
		}
		this.selectedChildWidget = page;
		this.selectedChild = page.widgetId;
		this._showChild(page);
		page.isFirstChild = (page == this.children[0]);
		page.isLastChild = (page == this.children[this.children.length-1]);
		dojo.event.topic.publish(this.widgetId+"-selectChild", page);
	},

	forward: function(){
		// Summary: advance to next page
		var index = dojo.lang.find(this.children, this.selectedChildWidget);
		this.selectChild(this.children[index+1]);
	},

	back: function(){
		// Summary: go back to previous page
		var index = dojo.lang.find(this.children, this.selectedChildWidget);
		this.selectChild(this.children[index-1]);
	},

	onResized: function(){
		// Summary: called when any page is shown, to make it fit the container correctly
		if(this.doLayout && this.selectedChildWidget){
			with(this.selectedChildWidget.domNode.style){
				top = dojo.html.getPixelValue(this.containerNode, "padding-top", true);
				left = dojo.html.getPixelValue(this.containerNode, "padding-left", true);
			}
			var content = dojo.html.getContentBox(this.containerNode);
			this.selectedChildWidget.resizeTo(content.width, content.height);
		}
	},

	_showChild: function(/*Widget*/ page) {
		// size the current page (in case this is the first time it's being shown, or I have been resized)
		if(this.doLayout){
			var content = dojo.html.getContentBox(this.containerNode);
			page.resizeTo(content.width, content.height);
		}

		page.selected=true;
		page.show();
	},

	_hideChild: function(/*Widget*/ page) {
		page.selected=false;
		page.hide();
	},

	closeChild: function(/*Widget*/ page) {
		// summary
		//	callback when user clicks the [X] to remove a page
		//	if onClose() returns true then remove and destroy the childd
		var remove = page.onClose(this, page);
		if(remove) {
			this.removeChild(page);
			// makes sure we can clean up executeScripts in ContentPane onUnLoad
			page.destroy();
		}
	},

	destroy: function(){
		this._beingDestroyed = true;
		dojo.event.topic.destroy(this.widgetId+"-addChild");
		dojo.event.topic.destroy(this.widgetId+"-removeChild");
		dojo.event.topic.destroy(this.widgetId+"-selectChild");
		dojo.widget.PageContainer.superclass.destroy.apply(this, arguments);
	}
});


dojo.widget.defineWidget(
    "dojo.widget.PageController",
    dojo.widget.HtmlWidget,
	{
		// summary
		//	Set of buttons to select a page in a page list.
		//	Monitors the specified PageContaine, and whenever a page is
		//	added, deleted, or selected, updates itself accordingly.

		templateString: "<span wairole='tablist' dojoAttachEvent='onKey'></span>",
		isContainer: true,

		// containerId: String
		//	the id of the page container that I point to
		containerId: "",

		// buttonWidget: String
		//	the name of the button widget to create to correspond to each page
		buttonWidget: "PageButton",

		// class: String
		//	Class name to apply to the top dom node
		"class": "dojoPageController",

		fillInTemplate: function() {
			dojo.html.addClass(this.domNode, this["class"]);  // "class" is a reserved word in JS
			dojo.widget.wai.setAttr(this.domNode, "waiRole", "role", "tablist");
		},

		postCreate: function(){
			this.pane2button = {};		// mapping from panes to buttons

			// If children have already been added to the page container then create buttons for them
			var container = dojo.widget.byId(this.containerId);
			if(container){
				dojo.lang.forEach(container.children, this.onAddChild, this);
			}

			dojo.event.topic.subscribe(this.containerId+"-addChild", this, "onAddChild");
			dojo.event.topic.subscribe(this.containerId+"-removeChild", this, "onRemoveChild");
			dojo.event.topic.subscribe(this.containerId+"-selectChild", this, "onSelectChild");
		},

		destroy: function(){
			dojo.event.topic.unsubscribe(this.containerId+"-addChild", this, "onAddChild");
			dojo.event.topic.unsubscribe(this.containerId+"-removeChild", this, "onRemoveChild");
			dojo.event.topic.unsubscribe(this.containerId+"-selectChild", this, "onSelectChild");
			dojo.widget.PageController.superclass.destroy.apply(this, arguments);
		},

		onAddChild: function(/*Widget*/ page){
			// summary
			//   Called whenever a page is added to the container.
			//   Create button corresponding to the page.
			var button = dojo.widget.createWidget(this.buttonWidget,
				{
					label: page.label,
					closeButton: page.closable
				});
			this.addChild(button);
			this.domNode.appendChild(button.domNode);
			this.pane2button[page]=button;
			page.controlButton = button;	// this value might be overwritten if two tabs point to same container

			var _this = this;
			dojo.event.connect(button, "onClick", function(){ _this.onButtonClick(page); });
			dojo.event.connect(button, "onCloseButtonClick", function(){ _this.onCloseButtonClick(page); });
		},

		onRemoveChild: function(/*Widget*/ page){
			// summary
			//   Called whenever a page is removed from the container.
			//   Remove the button corresponding to the page.
			if(this._currentChild == page){ this._currentChild = null; }
			var button = this.pane2button[page];
			if(button){
				button.destroy();
			}
			this.pane2button[page] = null;
		},

		onSelectChild: function(/*Widget*/ page){
			// Summary
			//	Called when a page has been selected in the PageContainer, either by me or by another PageController
			if(this._currentChild){
				var oldButton=this.pane2button[this._currentChild];
				oldButton.clearSelected();
			}
			var newButton=this.pane2button[page];
			newButton.setSelected();
			this._currentChild=page;
		},

		onButtonClick: function(/*Widget*/ page){
			// summary
			//   Called whenever one of my child buttons is pressed in an attempt to select a page
			var container = dojo.widget.byId(this.containerId);	// TODO: do this via topics?
			container.selectChild(page, false, this);
		},

		onCloseButtonClick: function(/*Widget*/ page){
			// summary
			//   Called whenever one of my child buttons [X] is pressed in an attempt to close a page
			var container = dojo.widget.byId(this.containerId);
			container.closeChild(page);
		},

		onKey: function(/*Event*/ evt){
			// summary:
			//   Handle keystrokes on the page list, for advancing to next/previous button

			if( (evt.keyCode == evt.KEY_RIGHT_ARROW)||
				(evt.keyCode == evt.KEY_LEFT_ARROW) ){
				var current = 0;
				var next = null;	// the next button to focus on

				// find currently focused button in children array
				var current = dojo.lang.find(this.children, this.pane2button[this._currentChild]);

				// pick next button to focus on
				if(evt.keyCode == evt.KEY_RIGHT_ARROW){
					next = this.children[ (current+1) % this.children.length ];
				}else{ // is LEFT_ARROW
					next = this.children[ (current+ (this.children.length-1)) % this.children.length ];
				}

				dojo.event.browser.stopEvent(evt);
				next.onClick();
			}
		}
	}
);

dojo.widget.defineWidget("dojo.widget.PageButton", dojo.widget.HtmlWidget,
{
	// summary
	//	Internal widget used by PageList.
	//	The button-like or tab-like object you click to select or delete a page

	templateString: "<span class='item'>" +
						"<span dojoAttachEvent='onClick' dojoAttachPoint='titleNode' class='selectButton'>${this.label}</span>" +
						"<span dojoAttachEvent='onClick:onCloseButtonClick' class='closeButton'>[X]</span>" +
					"</span>",

	// label: String
	//  Name to print on the button
	label: "foo",

	// closeButton: Boolean
	//	true iff we should also print a close icon to destroy corresponding page
	closeButton: false,

	onClick: function(){
		// summary
		//  Basically this is the attach point PageController listens to, to select the page
		this.focus();
	},

	onCloseButtonMouseOver: function(){
		// summary
		//	The close button changes color a bit when you mouse over
		dojo.html.addClass(this.closeButtonNode, "closeHover");
	},

	onCloseButtonMouseOut: function(){
		// summary
		// 	Revert close button to normal color on mouse out
		dojo.html.removeClass(this.closeButtonNode, "closeHover");
	},

	onCloseButtonClick: function(/*Event*/ evt){
		// summary
		//	Handle clicking the close button for this tab
	},

	setSelected: function(){
		// summary
		//	This is run whenever the page corresponding to this button has been selected
		dojo.html.addClass(this.domNode, "current");
		this.titleNode.setAttribute("tabIndex","0");
	},

	clearSelected: function(){
		// summary
		//	This function is run whenever the page corresponding to this button has been deselected (and another page has been shown)
		dojo.html.removeClass(this.domNode, "current");
		this.titleNode.setAttribute("tabIndex","-1");
	},

	focus: function(){
		// summary
		//	This will focus on the this button (for accessibility you need to do this when the button is selected)
		if(this.titleNode.focus){	// mozilla 1.7 doesn't have focus() func
			this.titleNode.focus();
		}
	}
});

// These arguments can be specified for the children of a PageContainer.
// Since any widget can be specified as a PageContainer child, mix them
// into the base widget class.  (This is a hack, but it's effective.)
dojo.lang.extend(dojo.widget.Widget, {
	// label: String
	//		Label or title of this widget.  Used by TabContainer to the name the tab, etc.
	label: "",

	// selected: Boolean
	//		Is this child currently selected?
	selected: false,

	// closable: Boolean
	//		True if user can close (destroy) this child, such as (for example) clicking the X on the tab.
	closable: false,	// true if user can close this tab pane

	onClose: function(){
		// summary: Callback if someone tries to close the child, child will be closed if func returns true
		return true;
	}
});
