/**
 * Photobox - Frame for photo and metadata (on category page)
 * @constructor
 * @param {Layout} layout - containing layout object
 * @param {Object} data - data for initialisation
 * @param {Boolean} showDate - show day of month in top left corner
 *
 * {Layout} layout - containing layout object
 * {String} hash, editedHash, date, filetype - Photo properties
 * {int} orientation, magrinTop, viewWidth, viewHeight, comments - Photo properties
 * {boolean} perDay - flag for views per day or total views
 * {float} hits - views or views per day
 * {HTMLObject} checkbox - checkbox for selecting photo
 * {HTMLObject} thumbImage - container for thumbnail
 * {HTMLObject} metaBox, metaBoxframe - containers for metabox popups
 * {boolean} metaLoaded - flag to indicate metadata loaded
 */
var Photobox = Class.create(Component);

Photobox.prototype.init = function(layout, data, showDate)
{
	if(data)
		this.loadData(data);
	this.showDate = showDate;
	this.layout = layout;
	if(this.contents)
		this.contents.appendChild(this.getPhotobox());
}

/**
 * Photobox.loadData - load all data
 * @method
 * @param {Object} data
 */
Photobox.prototype.loadData = function(data)
{
	this.data = data;
	if(data.nodeType)
	{
		this.loadPhotoXML(data);
		this.loadCategoryXML(data);
	}
	else
	{
		this.loadPhotoObject(data);
	}
}
/**
 * Photobox.loadPhotoXML - load photo data from XML node
 * @method
 * @param {XMLNode} node
 */
Photobox.prototype.loadPhotoXML = function(node)
{
	this.hash = node.getAttribute('hash');
	this.editedHash = node.getAttribute('editedhash');
	this.date = node.getAttribute('date');
	this.filetype = node.getAttribute('type');

	this.orientation = parseInt(node.getAttribute('orientation'));
	this.marginTop = parseInt(node.getAttribute('margin'));
	this.viewWidth = parseInt(node.getAttribute('width'));
	this.viewHeight = parseInt(node.getAttribute('height'));
	this.comments = parseInt(node.getAttribute('comments'));
	this.perDay = node.getAttribute('hitsperday') ? true : false
	this.hits = this.perDay ? parseFloat(node.getAttribute('hitsperday')) : parseInt(node.getAttribute('hits'));
}
/**
 * Photobox.loadPhotoObject - load photo data from object
 * @method
 * @param {Object} object
 */
Photobox.prototype.loadPhotoObject = function(object)
{
	for(var i in object)
		this[i] = object[i];
}
/**
 * Photobox.loadCategoryXML - load category data from XML node
 * @method
 * @param {XMLNode} node
 */
Photobox.prototype.loadCategoryXML = function(node)
{
	this.categories = node.getElementsByTagName('category')
}

/**
 * Photobox.getPhotobox - Renders the photobox element
 * @method
 * @return {HTMLObject} The rendered photobox element
 */
Photobox.prototype.getPhotobox = function(options)
{
	if(!options) options = {};
	var photoBox = this.getPhotoboxarea(options)

	return photoBox;
}

Photobox.prototype.getPhotoboxarea = function(options)
{
	var photoBox = new Element('div');
	photoBox.className = 'photobox';
	var dateLabel = photoBox.appendChild(new Element('div'));
	dateLabel.className = 'date';
	if(this.showDate)
	{
		dateLabel.innerHTML = this.date;
	}
	else
	{
		dateLabel.innerHTML = '&nbsp;';
	}

	photoBox.appendChild(this.getThumbnail(options));
	return photoBox;
}

/**
 * Photobox.writeCatList - write the infobox category list
 * @method
 */
Photobox.prototype.writeCatList = function()
{
	this.catList.removeChildren();
	$A(this.categories).each(function(cat) {
		var catListItem = this.catList.appendChild(new Element('li'));

		if(parseInt(cat.getAttribute('parentcat')) > 0)
			catListItem.appendChild(new Span(cat.getAttribute('parentname') + ' :: '));
		var category = parseInt(cat.getAttribute('category'));
		var catLink = new TextButton(this.layout.unasscatHash.bind(this.layout, category, this.hash), cat.getAttribute('name'));
		catListItem.appendChild(catLink);

		if(parseInt(cat.getAttribute('located')) && settings.google_maps_key)
		{
			var geoButton = new ImageButton(
				this.layout.geoTag.bind(this.layout, category), 'generated/icons/geotag.png', 'geotag', 'Find on map', 'generated/icons/hover_geotag.png' //lang
			);
			catListItem.appendChild($T(' '));
			catListItem.appendChild(geoButton);
		}
	}, this);
}
/**
 * Photobox.getThumbnail - Renders the thumbbox element
 * @method
 * @return {HTMLObject} The rendered thumbbox element
 */
Photobox.prototype.getThumbnail = function(options)
{
	this.metaLoaded = false;
	this.hover = false;

	var thumbBox = new Element('div');
	thumbBox.className = 'thumbbox';
	var thumb = thumbBox.appendChild(new Element('div'));
	var returnText = '';
	thumb.className = 'thumb';
	var boxSize = settings.thumb_size + (settings.thumb_padding * 2);
	thumb.style.height = (boxSize + 4) + 'px';

	this.thumbImage = thumb.appendChild(new ImageButton(this.layout.addView.bind(this.layout, this), ''));
	this.thumbImage.onmouseover = (function() { this.metaShow(); this.thumbImage.className = 'hover'; }).bind(this);
	this.thumbImage.onmouseout = (function() { this.metaHide(); this.thumbImage.className = ''; }).bind(this);
	this.writeThumbImage();

	var metaBoxContainer = thumbBox.appendChild(new Element('div'));
	metaBoxContainer.className = 'metabox_container';
	this.metaBox = metaBoxContainer.appendChild(new Element('div'));
	this.metaBox.className = 'metabox';
	this.metaBox.onmouseover = this.metaShow.bind(this);
	this.metaBox.onmouseout = this.metaHide.bind(this);
	Element.setOpacity(this.metaBox, 0.9);

	thumbBox.appendChild(this.getButtons(options));

	if(!settings.disable_stats && typeof this.hits != 'undefined')
	{
		var hitsText = thumbBox.appendChild(new Element('div'));
		hitsText.className = 'hits';
		hitsText.appendChild($T(this.hits + ' ' + (this.hits != 1 ? language('views') : language('view')) + (this.perDay ? ' per day' : ''))); //lang
	}
	if(this.messages && this.messages.length)
	{
		var messages = thumbBox.appendChild(new Element('ul'));
		messages.className = 'messages';
		for(var i = 0, il = this.messages.length; i < il; i++)
			messages.appendChild(new TextItem(this.messages[i]));
	}

	return thumbBox;
}
/**
 * Photobox.writeCatList - write the thumbnail image
 * @method
 */
Photobox.prototype.writeThumbImage = function()
{
	var scale = settings.thumb_size / Math.max(this.viewWidth, this.viewHeight);
	var thumbWidth = Math.round(this.viewWidth * scale);
	var thumbHeight = Math.round(this.viewHeight * scale);

	this.thumbImage.src = settings.thumbs_directory + '/' + filename(this.hash) + '.' + this.filetype + '?rot=' + this.orientation;
	this.thumbImage.alt = 'Thumbnail'; //lang
	this.thumbImage.style.marginTop = this.marginTop + 'px';
	//this.thumbImage.style.width = thumbWidth + 'px';
	//this.thumbImage.style.height = thumbHeight + 'px';
}

/**
 * Photobox.getButtons - Renders the thumbnail's buttons
 * @method
 * @return {HTMLObject} The thumbnail's buttons
 */
Photobox.prototype.getButtons = function(options)
{
	if(typeof(options) != 'object') options = {};

	var icons = new Element('div');
	icons.className = 'icons';

	var returnText = '';

	var viewable = (this.filetype == 'jpg' || this.filetype == 'png' || this.filetype == 'gif' || this.filetype == 'tif' || this.filetype == 'bmp');
	var zoomable = (this.filetype == 'jpg');

	if(viewable && !options.noViewButton)
	{
		icons.appendChild(new ImageButton(
			this.layout.addView.bind(this.layout, this), settings.images_out.view, 'View icon', language('view-title'), settings.images_over.view //lang
		));
	}

	if(zoomable)
	{
		icons.appendChild(new ImageButton(
			viewer.bind(window, this.hash), settings.images_out.zoomer, 'Zoom icon', language('zoom'), settings.images_over.zoomer //lang
		));
	}

	icons.appendChild(new ImageButton(
		(function() { location.href = 'download.php?hash=' + this.hash; }).bind(this),
		settings.images_out.download, 'Download icon', language('download'), settings.images_over.download //lang
	));

	icons.appendChild(new ImageButton(
		meta.bind(window, this.hash), settings.images_out.meta, 'Metadata icon', language('metadata'), settings.images_over.meta //lang
	));

	if(!settings.disable_comments && !options.noCommentsButton)
	{
		icons.appendChild(new ImageButton(
			this.layout.comment.bind(this.layout, this), (this.comments ? settings.images_out.comments : settings.images_out.addcomment), 'Comment icon', this.comments ? language('comments') : language('comments-add'), (this.comments ? settings.images_over.comments : settings.images_over.addcomment) //lang
		));
	}

	if(session.priv)
	{
		icons.appendChild(new ImageButton(
			cEdit.bind(window, this.hash), settings.images_out.edit, 'Edit icon', 'Edit picture', settings.images_over.edit //lang
		));
	}

	if(!options.noSlideshowButton)
	{
		icons.appendChild(new ImageButton(
			this.layout.loadData.bind(this.layout, {mode: 'slideshow', hash: this.hash}),
			settings.images_out.slide, 'Slideshow icon', 'Start slideshow', settings.images_over.slide //lang
		));
	}
	return icons;
}
/**
 * Photobox.getButtons - Generates the photo's view location
 * @method
 * @return {HTMLObject} The photo's view location
 */
Photobox.prototype.getViewSrc = function()
{
	var views_directory = this.editedHash ? settings.edited_directory + '/views' : settings.views_directory;
	return views_directory + '/' + filename(this.hash) + '.' + this.filetype;
}
/**
 * Photobox.metaHide - Set timeout to hide the metadata box
 * @method
 */
Photobox.prototype.metaHide = function()
{
	this.hover = false;
	window.clearTimeout(this.timer);
	this.timer = window.setTimeout(this.metaHide2.bind(this), 300);
}
/**
 * Photobox.metaHide2 - Hide the metadata box
 * @method
 * @param {boolean} force - hide the metadata box even if still hovering
 */
Photobox.prototype.metaHide2 = function(force)
{
	window.clearTimeout(this.timer);
	if(!this.hover || force)
		this.metaBox.hide()
}
/**
 * Photobox.metaShow - Set timeout to show the metadata box
 * @method
 */
Photobox.prototype.metaShow = function()
{
	this.hover = true;
	window.clearTimeout(this.timer);
	this.timer = window.setTimeout(this.metaShow2.bind(this), 500);
}
/**
 * Photobox.metaShow2 - Show the metadata box
 * @method
 */
Photobox.prototype.metaShow2 = function()
{
	this.metaBox.style.display = 'inline';

	if(!this.metaLoaded)
	{
		this.metaLoaded = true;
		var position = Position.cumulativeOffset(this.metaBox);
		this.metaBox.style.marginLeft = Math.max(10, 10 - position[0]) + 'px';
		this.metaBoxFrame = this.metaBox.appendChild(new Element('div'));
		this.metaBoxFrame.className = 'metabox_frame metadata';
		this.metaBoxFrame.innerHTML = language('loading') + '...';

		new RPC('ajax.loadmetadata.xml.php', {
			parameters: {
				hash: this.hash,
				priv: session.priv ? 1 : 0
			},
			onSuccess: (function(transport) {
				var xml = transport.responseXML;
				this.metaBoxFrame.removeChildren();
				this.metaBoxFrame.appendChild(this.getCategories(xml));
				this.metaBoxFrame.appendChild(this.getMetadata(xml));
				this.metaBoxFrame.appendChild(this.getComments(xml));
			}).bind(this)
		});
	}
}
/**
 * Photobox.getCategories - Renders the metabox's category list
 * @method
 * @param {XMLNode} xml - XML data
 * @return {HTMLObject} The metabox's category list
 */
Photobox.prototype.getCategories = function(xml)
{
	var list = new Element('div');

	var lastParent;
	var catListItem;

	var categories = xml.getElementsByTagName("category")
	for(var i = 0, il = categories.length; i < il; i++)
	{
		var parentCat = parseInt(categories[i].getAttribute('parentcat'));
		var located = parseInt(categories[i].getAttribute('located'));
		var hasCoords = parseInt(categories[i].getAttribute('hasCoords'));
		var category = parseInt(categories[i].getAttribute('category'));

		if(parentCat && parentCat != lastParent)
		{
			var parentItem = list.appendChild(new Element('div'));
			parentItem.className = 'parent';
			parentItem.innerHTML = categories[i].getAttribute('parentname');
		}
		catListItem = list.appendChild(new Element('div'));
		if(parentCat)
			catListItem.className = 'grouped_item';

		var catLink = catListItem.appendChild(new TextButton(this.layout.showCat.bind(this.layout, category), categories[i].getAttribute('name')));
		if(located && settings.google_maps_key)
		{
			catListItem.appendChild($T(' '));
			var geoButton = catListItem.appendChild(new ImageButton(
				this.layout.geoTag.bind(this.layout, category),
				'generated/icons/' + (hasCoords ? 'geotag' : 'located') + '.png', 'geotag', 'Find on map', 'generated/icons/hover_' + (hasCoords ? 'geotag' : 'located') + '.png' //lang
			));
		}
		lastParent = parentCat;
	}
	return list;
}
/**
 * Photobox.getMetadata - Renders the metabox's metadata list
 * @method
 * @param {XMLNode} xml - XML data
 * @return {HTMLObject} The metabox's metadata list
 */
Photobox.prototype.getMetadata = function(xml)
{
	var metadata = xml.getElementsByTagName("metadata")[0];
	var frame = new Element('div');
	if(metadata)
	{
		var list = frame.appendChild(new Element('ul'));
		list.className = 'meta';

		var taken;
		if(metadata.getAttribute('link'))
		{
			var YMD = metadata.getAttribute('link').split(',');
			taken = list.appendChild(new Element('li'));
			taken.appendChild(new TextButton(this.layout.loadData.bind(this.layout, {mode: 'calendar', year: parseInt(YMD[0]), month: parseInt(YMD[1]), day: parseInt(YMD[2])}), metadata.getAttribute('time')));
		}
		else
		{
			taken = list.appendChild(new TextItem(metadata.getAttribute('time')));
		}
		taken.className = 'taken';
		taken.title = language('taken');

		var resolution = list.appendChild(new TextItem(metadata.getAttribute('width') + ' &times; ' + metadata.getAttribute('height') + ' <small>(' + metadata.getAttribute('res') + ')</small>'));
		resolution.className = 'resolution';
		resolution.title = language('resolution');

		var filesize = list.appendChild(new TextItem(metadata.getAttribute('filesize')));
		filesize.className = 'filesize';
		filesize.title = language('filesize');

		if(metadata.getAttribute('make') || metadata.getAttribute('model'))
		{
			var camera = list.appendChild(new Element('li'));
			camera.appendChild(new TextButton(this.layout.setHardware.bind(this.layout, metadata.getAttribute('make') + ' || ' + metadata.getAttribute('model')), metadata.getAttribute('make') + ' ' + metadata.getAttribute('model')));
			camera.className = 'camera';
			camera.title = language('camera');
		}

		if(metadata.getAttribute('settings'))
		{
			var settings = list.appendChild(new TextItem(metadata.getAttribute('settings')));
			settings.className = 'camera_settings';
			settings.title = language('settings');
		}
	}
	return frame;
}
/**
 * Photobox.getComments - Renders the metabox's comment list
 * @method
 * @param {XMLNode} xml - XML data
 * @return {HTMLObject} The metabox's comment list
 */
Photobox.prototype.getComments = function(xml)
{
	var frame = new Element('div');

	var comments = xml.getElementsByTagName("comment");
	if(comments.length)
	{
		var list = frame.appendChild(new Element('ul'));
		list.className = 'comment_list';
		for(var i = 0, il = comments.length; i < il; i++)
		{
			var commentText = getNodeValue(comments[i]);
			if(commentText.length > 50)
				commentText = commentText.substring(0, 50) + '\u2026';
			var item = list.appendChild(new Element('li'));
			var span = item.appendChild(new Span(''));
			span.appendChild($T('\u201C'));
			var comment = span.appendChild(new TextButton(this.layout.comment.bind(this.layout, this), commentText));
			span.appendChild($T('\u201D'));
			comment.title = 'Comment'; //lang
		}
	}

	return frame;
}
/**
 * Photobox.getMetaBar - Renders the metabar
 * @method
 * @param {XMLNode} xml - XML data
 * @return {HTMLObject} The metabar
 */
Photobox.prototype.getMetaBar = function(xml)
{
	var metaBar = new Element('div');
	metaBar.className = 'metadata';

	var categories = metaBar.appendChild(this.getCategories(xml));
	categories.className = 'metadata_cell';

	var metadata = metaBar.appendChild(this.getMetadata(xml));
	metadata.className = 'metadata_cell';

	var comments = metaBar.appendChild(this.getComments(xml));
	comments.className = 'metadata_cell';

	metaBar.appendChild(new Lineclear());
	return metaBar;
}
