﻿/*
		TagCloud	
*/

AUI.widgets.TagCloud = new Class({

	Extends: AUI.widgets.Base,

	options: {
		data: null, /*{
			archaic: { id: 1, frequency: 2 }
		},*/
		dataItemMapper: null,
		classes: {
			min: '.tagCloudMin',
			max: '.tagCloudMax',
			visible: '.tagCloudVisible',
			hidden: '.tagCloudHidden'
		},
		hover: {
			onOverOut: ['.over', '.out'],
			onSelectionChange: $empty
		},
		morphFxOptions: {
			duration: 500, transition: 'linear'
		}
	},

	initialize: function(el, options) {
		this.parent(el, options);
		this.itemClone = this.element.getElement('li').dispose();
		this.element.empty();
		this.setTagSizes();
		this.tags = [];
		this.setData(this.options.data);
	},

	setTagSizes: function() {
		this.styles = {};
		['min', 'max', 'visible', 'hidden'].each(function(prop) {
			this.styles[prop] = Fx.CSS.prototype.search(this.options.classes[prop]);
		}, this);
		this.tagSizes = [];
		for (var i = parseInt(this.styles.min.fontSize); i <= parseInt(this.styles.max.fontSize); i++) this.tagSizes.push(i + 'px');
		this.depth = this.tagSizes.length;
	},

	setData: function(data, animate) {
		this.previousData = this.data || {};
		this.data = data;
		this.setBounds();
		this.updateTags();
		this.sortTags();
		this.draw(animate);
	},

	setBounds: function() {
		this.bounds = { upper: 0, lower: 9999999999 };
		$each(this.data, function(v, k) {
			if (v > this.upper) this.upper = v;
			if (v < this.lower) this.lower = v;
		}, this.bounds);
	},

	updateTags: function() {
		$each(this.data, function(v, k) {
			var item = this.tags.find(function(item) { return item.tag == k; });
			if (!item) this.tags.push(item = {
				tag: k,
				el: this.itemClone.clone(false).set('html', k + '\n'),
				toString: function() { return this.tag; }
			});
			item.weight = this.getWeight(v);
		}, this);
	},

	sortTags: function() {
		this.tags.sort();
		var cache = this.element.ownerDocument.createDocumentFragment();
		this.tags.each(function(tag) { cache.appendChild(tag.el); });
		this.element.appendChild(cache);
	},

	getWeight: function(frequency) {
		var weight = Math.floor(parseFloat(((frequency - this.bounds.lower) / (this.bounds.upper - this.bounds.lower)), this.depth) * this.depth);
		if (weight == this.depth) weight--;
		return weight;
	},

	draw: function(animate) {
		var els = this.tags.map(function(item) { return item.el; });
		var fx = new Fx.Elements(els, this.options.morphFxOptions);
		var params = this.tags.map(function(item) {
			return $merge(this.styles[this.data[item.tag] ? 'visible' : 'hidden'], {
				fontSize: this.tagSizes[item.weight]
			});
		}, this);
		fx[animate ? 'start' : 'set'](params);
	}
});