/*
 * Copyright 2006, Jeffrey Palm.
 */


Flickr.NodeFormat = Class.create();

Flickr.NodeFormat.prototype = {

	initialize: function() {

	},

	// --------------------------------------------------
	// Flickr.PhotoNode
	// --------------------------------------------------

	/**
	 * Flickr.Service,Flickr.Photo,(HTML -> Void)
	 * TODO: This should be put in tree.js
	 */
	getPhotoHTML: function(api,photo,node,callback) {
		var thiz = this;
		photo.getInfoXML
		(function(doc) {
				/*
<photo id="2733" secret="123456" server="12"
	isfavorite="0" license="3" rotation="90" originalformat="png">
	<owner nsid="12037949754@N01" username="Bees"
		realname="Cal Henderson" location="Bedford, UK" />
	<title>orford_castle_taster</title>
	<description>hello!</description>
	<visibility ispublic="1" isfriend="0" isfamily="0" />
	<dates posted="1100897479" taken="2004-11-19 12:51:19"
		takengranularity="0" lastupdate="1093022469" />
	<permissions permcomment="3" permaddmeta="2" />
	<editability cancomment="1" canaddmeta="1" />
	<comments>1</comments>
	<notes>
		<note id="313" author="12037949754@N01"
			authorname="Bees" x="10" y="10"
			w="50" h="50">foo</note>
	</notes>
	<tags>
		<tag id="1234" author="12037949754@N01" raw="woo yay">wooyay</tag>
		<tag id="1235" author="12037949754@N01" raw="hoopla">hoopla</tag>
	</tags>
	<urls>
		<url type="photopage">http://www.flickr.com/photos/bees/2733/</url> 
	</urls>
</photo>
				*/
			var id = photo.getId();
			var ph = doc.getElementsByTagName('photo')[0];
			var secret = ph.getAttribute('secret');
			var server = ph.getAttribute('server');
			var originalformat = ph.getAttribute('originalformat');
			var url = imageURL(id,secret,server);
			
			var title = photo.getTitle();
			var description = '';
			var descriptions = doc.getElementsByTagName('description');
			if (descriptions) {
				var dNode = descriptions[0];
				if (dNode && dNode.firstChild) {
					description = dNode.firstChild.nodeValue;
				}
			}
			
			var top = $n('div');

			var tab = $n('table');
			tab.width = "100%";
			top.appendChild(tab);

			var tr,td;

			tr = $n('tr');
			tab.appendChild(tr);

			// title at the top
			td = $n('td');
			tr.appendChild(td);
			td.style.textAlign = 'left';
			td.className = "canvasTitle";
			var titleNode = $t(title);
			td.appendChild(titleNode);

			tr = $n('tr');
			tab.appendChild(tr);

			td = $n('td');
			tr.appendChild(td);

			// image and desription
			var img = $n('img');
			img.src = url;
			img.style.maxHeight = "350px";
			img.style.border = "solid black 1px";
			td.appendChild(img);
			td.appendChild($n('br'));
			td.appendChild($t(description));

			// links on the right
			td = $n('td');
			tr.appendChild(td);
			td.style.textAlign = 'left';
			td.style.verticalAlign = 'top';

			function ss(t,name,td) {
				var url = imageURL(id,secret,server,t);
				if (url == null) return;
				var a = $n('a');
				td.appendChild(a);
				a.target = '_';
				a.href = url;
				a.appendChild($t(name));
				td.appendChild($n('br'));
			}

			ss('s', 'small',td);
			ss('t', 'thumbnail',td);
			ss('-','medium',td);
			ss('b','large',td);
			ss('o','original',td);
			
			td.appendChild($n('br'));
			td.appendChild($n('br'));
			
			// next and prev
			tab = $n('table');
			td.appendChild(tab);
			tab.style.cellPadding = "0px";
			tab.style.cellSpacing = "1px";
			tr = $n('tr');
			tab.appendChild(tr);

			function navLink(prevNode, title) {
				td = $n('td');
				tr.appendChild(td);
				td.width = '75px';
				if (prevNode) {
					a = $n('a');
					td.appendChild(a);
					img = $n('img');
					a.appendChild(img);
					img.style.border = 'solid black 1px';
					img.src = prevNode.getPhoto().getURL('s');
					a.appendChild($n('br'));
					a.href = "javascript:void(0)";
					a.onclick = thiz._n(api,prevNode);
					a.appendChild($t(title));
				}
			}


			navLink(api.getPrevNode(node), 'prev');
			navLink(api.getNextNode(node), 'next');

			callback(top);
				
			});
	},

	_n: function(api,node) {
		return function(event) {
			api.showOnCanvas(node);
		};
	},

	_f: function(ph,api) {
		return function(event) {													 
			api.showOnCanvas(ph);
		};
	},

	/**
	 * Flickr.Service,Flickr.Photo,(HTML -> Void)
	 * TODO: This should be put in tree.js
	 */
	getPhotoMapHTMLFull: function(api,photo,node,callback) {
		var thiz = this;
		photo.getInfoXML
		(function(doc) {
				/*
<photo id="2733" secret="123456" server="12"
	isfavorite="0" license="3" rotation="90" originalformat="png">
	<owner nsid="12037949754@N01" username="Bees"
		realname="Cal Henderson" location="Bedford, UK" />
	<title>orford_castle_taster</title>
	<description>hello!</description>
	<visibility ispublic="1" isfriend="0" isfamily="0" />
	<dates posted="1100897479" taken="2004-11-19 12:51:19"
		takengranularity="0" lastupdate="1093022469" />
	<permissions permcomment="3" permaddmeta="2" />
	<editability cancomment="1" canaddmeta="1" />
	<comments>1</comments>
	<notes>
		<note id="313" author="12037949754@N01"
			authorname="Bees" x="10" y="10"
			w="50" h="50">foo</note>
	</notes>
	<tags>
		<tag id="1234" author="12037949754@N01" raw="woo yay">wooyay</tag>
		<tag id="1235" author="12037949754@N01" raw="hoopla">hoopla</tag>
	</tags>
	<urls>
		<url type="photopage">http://www.flickr.com/photos/bees/2733/</url> 
	</urls>
</photo>
				*/
			var ph = doc.getElementsByTagName('photo')[0];
			/*var id = photo.getId();
			
			var secret = ph.getAttribute('secret');
			var server = ph.getAttribute('server');
			var originalformat = ph.getAttribute('originalformat');
			var url = imageURL(id,secret,server,'t');
			*/
			var url = photo.getURL('m');
			
			var title = photo.getTitle();
			var description = '';
			var descriptions = doc.getElementsByTagName('description');
			if (descriptions) {
				var dNode = descriptions[0];
				if (dNode && dNode.firstChild) {
					description = dNode.firstChild.nodeValue;
				}
			}

			var div;
			
			var top = $n('div');
			
			top.style.maxWidth="300px";
			
			div  = $n('div');
			top.appendChild(div);
			div.style.textAlign = 'left';
			div.className = "canvasTitleSmall";
			var titleNode = $t(title);
			div.appendChild(titleNode);


			var a = $n('a');
			top.appendChild(a);
			a.onclick = thiz._f(ph,api);
			a.href = "javascript:void(0)";
			
			var img = $n('img'); 
			a.appendChild(img);
			img.src = url;
			img.style.border = "solid black 1px";
			top.appendChild($n('br'));
			div = $n('div');
			top.appendChild(div);
			div.style.whiteSpace = "nowrap";
			div.style.width = "200px";
			// skip this for now, it's no wrapping
			//div.appendChild($t(description));

			callback(top);
				
			});
	},

	/**
	 * Flickr.Photo Jeff.API (DOMElement[html] -> Void) -> Void
	 * @interface
	 */
	getPhotoMapHTML: function(that, api, callback) {
		var top = $n('div');
		
		var image = that.getURL('m');
		
		// these won't have be resolved yet

		var img = $n('img');
		top.appendChild(img);
		img.src = image;

		callback(top);
	},
	
	/**
	 * Flickr.PhotoSet Jeff.API (String|DOM) -> _
	 */
	getPhotoSetMainHTML: function(that, api, callback) {
		var thiz = this;
		that.getChildren(api, function(ps) {

											 var top = $n('div');
											 
											 var tab = $n('table');
											 top.appendChild(tab);
											 
											 var tr,td;
											 
											 tr = $n('tr');
											 tab.appendChild(tr);

											 
											 td = $n('td');
											 tr.appendChild(td);
											 td.style.textAlign = 'left';
											 td.className = "canvasTitle";
											 var span = $n('span');
											 span.style.margin = "2px";

											 span.appendChild($t(that.toString()));
											 td.appendChild(span);

											 tr = $n('tr');
											 tab.appendChild(tr);
											 
											 td = $n('td');
											 tr.appendChild(td);
											 td.style.textAlign = 'center';
											
											 
											 tab = $n('table');
											 tab.style.border = "0";
											 tab.style.cellPadding = "0px";
											 tab.style.cellSpacing = "0px";
											 td.appendChild(tab);

											 for (var i=0; i<ps.length; i++) {

												 if (i%6==0) tab.appendChild(tr = $n('tr'));
												 
												 var ph = ps[i];
												 var url = ph.getURL('t');

												 td = $n('td');
												 tr.appendChild(td);
												 td.style.textAlign = 'center';

												 var a = $n('a');
												 td.appendChild(a);
												 a.onclick = thiz._f(ph,api);
												 a.href = "javascript:void(0)";
												 
												 var img = $n('img'); 
												 a.appendChild(img);

												 img.src = url; 
												 img.style.margin = "2px"; 
												 img.style.border = "solid black 1px;"; 											 
												 
											 }
											 callback(top);
										 });

	},

	_dummy: function() {}
};

var nodeFormat = new Flickr.NodeFormat();




//
// here we add the node attributes to the Flickr elements
//

Flickr.UserNode = Class.create();
Flickr.UserNode.prototype = {

	initialize: function(user,isRoot) {
		this.user = user;
		this.isRoot = isRoot;
	},

	toString: function() {
		var s = '';
		if (this.isRoot) s += this.getName() + " (";
		s += this.user.getName();
		if (this.isRoot) s += ")";
		return s;
	},

	getNodesForLocation: function(api, loc, jeffPoint, callback) {
		var thiz = this;
		this.user.getPhotosForLocation(loc, function(photos) {
																		 var nodes = new Array();
																		 //
																		 // these nodes need to be able to be shown on a map
																		 // so make their getPoint function something near the center
																		 //
																		 if (photos) {
																			 for (var i=0; i<photos.length; i++) {
																				 var photo = photos[i];
																				 var node = new Flickr.PhotoNode(photo);
																				 node.getPoint = thiz._newPoint(api,callback,i,jeffPoint);
																				 nodes.push(node);
																			 }
																		 }
																		 callback(nodes);
																	 });
	},

	_newPoint: function(api, callback, i, jeffPoint) {
		//TODO: This is very dependent on the map (booooo!)
		var x = 1.8*Math.random() - 0.9;
		var y = 0.9*Math.random() - 0.45;
		var newPoint = new Jeff.Point(jeffPoint.getLon()+x, jeffPoint.getLat()+y);
		return function(api, callback) {
			callback(newPoint);
		};
	},

	getChildren: function(api,callback) {
		callback([ 
							new Flickr.ContactsNode(this.user),
							new Flickr.PhotoSetsNode(this.user),
							new Flickr.PhotosNode(this.user),
							 ]);
	},	

	/*	onClick: function(api) {
		api.showMainHTML();
		},*/

	getMainHTML: function(api, callback) {
		var div = $n('div');
		div.textAlign = 'center';
		div.appendChild($t('I am the '));
		var b = $n('b',div);
		b.appendChild($t(this.user.getName()));

		div.appendChild($n('br'));
		div.appendChild($n('br'));

		var form = $n('form',div);

		var input = $n('input',form);
		input.type='text';
		input.name='flickr';
		input.id='flickr';
		input.size=30;

		var button = $n('input',form);
		button.type='submit';
		//button.name='submit';
		button.id='submit';
		button.value='Change User!';

		callback(div);
	},

	getIcon: function() {
		return 'upload/icon.jpg';
	},

	getName: function() {
		return 'Flickr';
	},

	_dummy: function() {}

};

Flickr.PhotoSetsNode = Class.create();
Flickr.PhotoSetsNode.prototype = {
	
	initialize: function(user) {
		this.user = user;
		
	},

	toString: function() {
		return "Sets";
	},
	
	getChildren: function(api,callback) {
		this.user.getSets
 		(function(ps) {
			var kids = [];
			for (var i=0; i<ps.length; i++) {
				kids.push(new Flickr.PhotoSetNode(ps[i]));
			}
			callback(kids);
		});
	},

	_dummy: function() {}
	
};

Flickr.PhotoSetNode = Class.create();
Flickr.PhotoSetNode.prototype = {
	
	initialize: function(p) {
		// Flickr.PhotoSet
		this.p = p;
		// we save these so we can use getChildren to get the main html
		// TODO: This breaks the interface a little (?)
		this.kids = 0;		
	},

	toString: function() {
		return this.p.getTitle(); // + " (" + this.p.getId() + ")";
	},

	/**
	 * @interface
	 */
	getMainHTML: function(api, callback) {
		nodeFormat.getPhotoSetMainHTML(this, api, callback);
	},
	
	getChildren: function(api,callback) {
		if (this.kids) {
			callback(this.kids);
			return;
		}
		//
		// we want to save the kids
		//
		var thiz = this;
		this.p.getPhotos(function (kids) {
											 thiz.kids = new Array();
											 $A(kids).each(function(photo) {
																			 thiz.kids.push(new Flickr.PhotoNode(photo));
																		 });
											 callback(thiz.kids);
										 });
	},

	_dummy: function() {}
};

Flickr.ContactsNode = Class.create();
Flickr.ContactsNode.prototype = {
	
	initialize: function(user) {this.user = user;},

	toString: function() {
		return "Contacts";
	},
	
	getChildren: function(api,callback) {
		this.user.getContacts
		(function(ps) {
			var kids = [];
			for (var i=0; i<ps.length; i++) {
				kids.push(new Flickr.UserNode(ps[i]));
			}
			callback(kids);
		});
	},

	_dummy: function() {}
	
};


Flickr.PhotosNode = Class.create();
Flickr.PhotosNode.prototype = {
	
	/**
	 * isMain: true if this is the top node, if so we'll include the user's
	 *         name in toString()
	 */
	initialize: function(user,isMain) {
		this.user = user;
		this.isMain = isMain;
	},

	toString: function() {
		var s = "Photos";
		if (this.isMain) s += " for " + this.user.getName();
		return s;
	},
	
	getChildren: function(api,callback) {
		this.user.getPages
		(function(ps) {
			var kids = [];
			for (var i=0; i<ps.length; i++) {
				kids.push(new Flickr.PageNode(ps[i]));
			}
			callback(kids);
		});
	},

	_dummy: function() {}
	
};

Flickr.PhotoNode = Class.create();
Flickr.PhotoNode.prototype = {
	
	initialize: function(p) {this.p = p;},

	toString: function() {
		return this.p.getTitle();
	},

	getPhoto: function() {
		return this.p;
	},

	/**
	 * @interface
	 */
	getMapHTML: function(api, callback) {
		//nodeFormat.getPhotoMapHTML(this, api, callback);
		nodeFormat.getPhotoMapHTMLFull(api,this.p,this,callback);
	},

	/**
	 * @interface
	 */
	/**
	 * @interface
	 */
	getPoint: function(api, callback) {
		//
		// these will be assigned randomly
		//
	},
	
	/**
	 * Jeff.API (String[html] -> _ ) -> _
	 * @interface
	 */
	getMainHTML: function(api, callback) {
		nodeFormat.getPhotoHTML(api,this.p,this,callback);
	},

	getURL: function(kind) {
		return this.p.getURL(kind);
	},

	_dummy: function() {}
};

Flickr.PageNode = Class.create();
Flickr.PageNode.prototype = {
	
	initialize: function(p) {
		this.p = p;
		// we save these so we can use getChildren to get the main html
		// TODO: This breaks the interface a little (?)
		this.kids = 0;
	},

	toString: function() {
		return "Page " + this.p.toString();
	},
	
	getChildren: function(api,callback) {
		if (this.kids) {
			callback(this.kids);
			return;
		}
		var thiz = this;
		this.p.getOwner().getPhotos
		(function(ps) {
			thiz.kids = [];
			for (var i=0; i<ps.length; i++) {
				thiz.kids.push(new Flickr.PhotoNode(ps[i]));
			}
			callback(thiz.kids);
		}, 
		 this.p.getNum()
		 );
	},

	/**
	 * @interface
	 */
	getMainHTML: function(api, callback) {
		//nodeFormat.getMainHTML(this, api, callback);
		nodeFormat.getPhotoSetMainHTML(this, api, callback);
	},

	_dummy: function() {}

};


// --------------------------------------------------
// Reflect
// --------------------------------------------------

Flickr.ReflectNode = Class.create();
Flickr.ReflectNode.prototype = {
	
	initialize: function(reflect) {
		this.reflect = reflect;
	},

	getChildren: function(api,callback) {
		var kids = [];
		var cb = function(ms) {
			if (ms) {
				for (var i=0; i<ms.length; i++) {
					var m = ms[i];
					var n = new Flickr.MethodNode(m);
					kids.push(n);
				}
				callback(kids);
			}
		};
		this.reflect.getMethods(cb);
	},

	toString: function() {
		return this.reflect.toString();
	},

	_dummy: function() {}
};

Flickr.MethodNode = Class.create();
Flickr.MethodNode.prototype = {
	
	initialize: function(method) {
		this.method = method;
	},

	getChildren: function(api,callback) {
		var cb = function(xml) {
			var kid = new Flickr.XMLNode(xml);
			var kids = [kid];
			callback(kids);
		}
		this.method.getXML(cb);
	},

	toString: function() {
		return this.method.toString();
	},

	_dummy: function() {}
};

Flickr.XMLNode = Class.create();
Flickr.XMLNode.prototype = {
	
	initialize: function(xml) {
		this.xml = xml;
	},

	getChildren: function(api,callback) {
		//
		// if we have only one kid and it's text, just put it on a line
		//
		if (this._isText()) return 0;
		//
		// otherwise fill them up
		//
		var kids = [];
		for (var i=0; i<this.xml.attributes.length; i++) {
			var a = this.xml.attributes[i];
			var n = new Flickr.AttributeNode(a.nodeName,a.nodeValue);
			kids.push(n);
		}
		for (var i=0; i<this.xml.childNodes.length; i++) {
			var xml = this.xml.childNodes[i];
			var n=0;
			if(xml.nodeName == "#text") {
				var v = xml.nodeValue;
				if (v) {
					var txt = v.replace(' ','');
					if (txt.length!='') {
						// skip this now kids.push(new Flickr.TextNode(v));
					}
				}
			} else {
				if (this.xml.nodeName.replace(' ','') != '') {
					kids.push(new Flickr.XMLNode(xml));
				}
			}
		}
		callback(kids);
	},

	_isText: function() {
		return this.xml.childNodes.length==1
		&&     this.xml.childNodes[0].nodeName == "#text";
	},

	toString: function() {
		//
		// if we have only one kid and it's text, just put it on a line
		//
		var r;
		if (this._isText()) {
			r = this.xml.nodeName + " = "
			+   this.xml.childNodes[0].nodeValue;
		} else {
			r = "(" + this.xml.nodeName + ")"
		}
		return r;
	},

	_dummy: function() {}
};

Flickr.AttributeNode = Class.create();
Flickr.AttributeNode.prototype = {
	
	initialize: function(name,value) {
		this.name = name;
		this.value = value;
	},

	toString: function() {
		return this.name + ": " + this.value;
	},

	_dummy: function() {}
};

Flickr.TextNode = Class.create();
Flickr.TextNode.prototype = {
	
	initialize: function(text) {
		this.text = text;
	},

	toString: function() {
		return this.text + ":" + this.text.length;
	},

	_dummy: function() {}
};

