// content.js


// <![CDATA[



// DataSources 
var DataSource = Class.extend({
	
	// C-tor
	construct: function(props) {
		
		// Setup properties
		// Override any default values with props passed in
		var defaults = {
			    
		};
		this.props = mergeWithDefaults(props,defaults);
	},
	
	// Functions below need to be overridden by specialised classes
	// to do anything useful
	
	// Has the data changed - must be overidden
	isChanged: function(key) {
	},
	
	// Get data - called initially or when 
	// isChanged returns true
	// Data returned must be a string or HTML segment
	// key: A key to identify the data - if '.' separated - identifies subpages
	getData: function(key) {
		return "No Data";
	},
	
	getClass: function(key) {
		return null;
	},
	
	getStyle: function(key) {
		return null;
	},
	
	// Get above in one go
	// Returns an object containing the data, class and style
	getDCS: function(key) {
		return { data:"No Data", _class:null, style:null };
	}
});


// Default DataSource - takes an array e.g. mainpages
// which contains elements with : name, class, content etc.
var DefaultDS = DataSource.extend({
	
	// C-tor
	construct: function(data,props) {
		// Call super method
		arguments.callee.$.construct.call(this, props);
		
		this.data = data;
		
	},
	
	// Default DS deems data is always up to date
	isChanged: function() {
		return false;
	},
	
	// Get the object identified by key (RDN) 
	// TODO handle dns name i.e. subpages
	get: function(key, data) {

		for (ind in data) {
			if (data[ind].name == key) {
				return data[ind];
			}
		}
		return null;
	},
	
	// Get child distinguished names
	// Used for menus and navigating to the object
	children: function(key) {
		var obj = this.traverse(key);
		var _children = [];
		var name;
		for (i in obj.subpages) {
			name = key+'.'+obj.subpages[i].name;  // Full distinguished name
			console.log("DN for child is: "+name);
			_children[i]=name;
		}
		return _children;
	},
	
	traverse: function(key) {
		// Traverse DN i.e. dot separated
		var dn = key.split('.');	
		
		// Get root object 
		var rdn = dn[0];
		var data = this.data;
		var obj = this.get(rdn, data);
		
		// Traverse if more tokens
		for (i=1;i<dn.length;i++) { // ignore root
			data = obj.subpages;
			rdn=dn[i];
			obj = this.get(rdn, data);
		}

		return obj;
	},
	
	
	// Todo handle hierarchy
	getData: function(key) {
		var obj = this.traverse(key);
		if (obj) {
			return (obj.createFn)?obj.createFn():obj.content;
		}
		return "No Data";
	},
	
	getClass: function(key) {
		var obj = this.traverse(key);
		if (obj && obj._class)
			return obj._class;
		return null;
	},
	
	getStyle: function(key) {
		var obj = this.traverse(key);
		if (obj && obj.style)
			return obj.style;
		return null;
	},
	
	// Get above in one go
	// Returns an object containing the data, class and style
	getDCS: function(key) {
		var obj = this.traverse(key);
		if (obj)
			return { data:(obj.createFn)?obj.createFn():obj.content, _class:obj._class, style:obj.style };
		return { data:"No Data", _class:null, style:null };
	},
	
	// Get Top Menu and submenus
	getMenu: function(key) {
		var obj = this.traverse(key);
		if (obj)
			return obj.menu;
		return "";
	}
	
});


// Layouts

var Layout = Class.extend({
	
	// C-tor
	construct: function(props) {
		
		// Setup properties
		// Override any default values with props passed in
		var defaults = {
			    
		};
		this.props = mergeWithDefaults(props,defaults);
	}
});

var StackLayout = Layout.extend({
	
	
	// C-tor
	// callBack - called when stackLayout is changed - takes this as argument
	// contentID: ID of HTML tag where the stacks will be added to the document
	// menuID: ID of HTML tag where sub menus will be placed
	// dataSource: must be of type DataSource
	construct: function(cb, contentID, menuID, dataSource, props){
		// Call super method
		arguments.callee.$.construct.call(this, props);
		
		this.cb = cb;
		this.contentID = contentID;
		this.menuID = menuID;
		this.dataSource = dataSource;
		
		// Stores jquery instances of data html segment
		this.stacks = [];
	},
	
	// replace .'s with _, because it causes jquery confusion
	convert: function(name) {
		var chgd = name.replace(/\./g,'_');
		return chgd;
	},
	
	// Returns the jquery of the built div
	buildDiv: function(name) {
		var obj = this.dataSource.getDCS(name);
		var data = obj.data;
		var _class = obj._class;
		var style = obj.style;
		
		var id = this.convert(name);  // Make name single word i.e. concatenate rdns with _
		var jq = $('#'+this.contentID);
		if (jq) {
			var div = '<div id="' +
				id +
				'" ' +
				((_class) ? 'class="' + _class + '" ' : '') +
				((style) ? 'style="' + style + '" ' : '') +
				' >' +
				data +
				'</div>';
			
			jq.append(div);
			
			return jq.find('#' + id);
		}
	
		console.log("No content DIV found");
		return null;
	},
	
	// Build sub menu
	buildMenu: function(name) {
		var menu = this.dataSource.getMenu(name);
		var id = this.convert(name)+"_menu";  // Make name single word i.e. concatenate rdns with _
		var _children = this.dataSource.children(name);
		var jq = $('#'+this.menuID);
		
		var span = '<span id="'+id+'">\
					<em style="color:green;font-size:16px;"><i>'+menu+'</i></em>'
		span = span+'<ul id="list-menu">';
		// Get sub menus
		for (i in _children) {
			//console.log("Child menu:"+this.dataSource.getMenu(_children[i]));
			span = span+'<li><a href="#" onclick="sl.setCurrent\(\''+_children[i]+'\'\);return false;">'+
			this.dataSource.getMenu(_children[i])+'</a></li>';
		}
		span += '</ul></span>'
		
		jq.append(span);
		
		return jq.find('#' + id);
	},
	
	getPage: function() {
		return this.page;
	},
	
	
	// Set the current stack - hides previous
	setCurrent: function(name) {
		
		this.page = name;
		
		if (null != this.current) {
			this.current.content.hide(); 
			this.current.menu.hide();
			
			// TODO push current onto a stack for back button
		}
		if (null == this.stacks[name]) {
			// Create the stack div
			this.stacks[name] = {
				content: this.buildDiv(name),
				menu: this.buildMenu(name)
			};
			this.current = this.stacks[name];
		}
		else {
			// Check if data is up to date
			if (this.dataSource.isChanged(name)) {
				// TODO remove div
				
				// TODO re-build div

			}
			this.current = this.stacks[name];
		}
			
		this.current.content.show();
		this.current.menu.show();
		
		// Call callback
		if (this.cb)
			this.cb(this);
			
	}
	

	
});




// ]]>