var defaultSettings = {
	styles: {
		opacity: 0
	},
	fx: {
		duration: 'short',
		transition: 'quint:in:out'
	},
	morph: {
		opacity: 0
	}
}

var Chains = new Class({
	Implements: [Chain, Events],

	elements: new Hash({}),

	initialize: function(elements) {
		this.isCompleted = false;
		this.elements = elements;

		this.elements.each(function(element) {
			element.content.each(function(item) {
				this.prepareItem(item);
			}.bind(this));
		}.bind(this));
	},

	prepareItem: function(item) {
    this.settings = {};
    if(item.retrieve('configuration')) this.settings = item.retrieve('configuration');
      else if(item.get('configuration')) this.settings = JSON.decode(item.get('configuration'));
        else return false;

		if(this.settings.styles) {
			var options = $merge(defaultSettings.styles, this.settings.styles);
			//item.store('styles', options);
			item.setStyles(options); //Apply styles instantly
		}

		if(this.settings.fx) {
			var fx = $merge(defaultSettings.fx, {
				onComplete: function() {
					//console.log('fx completed');
					if(!this.callChain()) this.complete();
				}.bind(this)
			});
			var options = $merge(fx, this.settings.fx);
			var itemFx = new Fx.Morph(item, options);
			item.store('fx', itemFx);
		}

		if(this.settings.morph) {
			var options = $merge(defaultSettings.morph, this.settings.morph);
			item.store('morph', options);
		}
    return item;
	},

	startup: function() {
		//console.log('this.elements: ', this.elements);
		this.elements.each(function(parent) {
			//console.log('parent: ', parent);
			parent.content.each(function(item) {
				//console.log('item: ', item);
				this.chain(
					function() {
					  //console.log('startup.chain fn 1: ', item);
						if(item.retrieve('fx') && item.retrieve('morph')) item.retrieve('fx').start(item.retrieve('morph'));
						  else this.callChain();
					},

					function() {
					  //console.log('startup.chain fn 2');
						if(item.retrieve('startup')) {
						  //console.log('startup present')
							item.retrieve('startup').startup();
						} else {
						  //console.log('startup not present');
						}
						if(!this.callChain()) this.complete(item);
					}
				)
			}.bind(this));
		}.bind(this));
		this.callChain();
	},

	complete: function(element) {
		if(!this.isCompleted) {
			this.isCompleted = true;
			this.fireEvent('chainComplete', element);
		}
	},

	isComplete: function() {
		return this.isCompleted;
	},

	stop: function() {
		this.clearChain();
	},

	reInit: function() {
		this.callChain();
	}
});

var assetChain = new Class({
	Extends: Chains,

	started: false,

	initialize: function(asset) {
	  this.isCompleted = false;
		this.asset = asset;
		this.prepareItem();
	},

  prepareItem: function() {
    this.parent(this.asset);
		if(this.settings.original) this.asset.store('original', this.settings.original);
    if(this.settings.href) this.asset.store('href', this.settings.href);
		if(this.settings.image) this.asset.store('image', this.settings.image);
		if(this.settings.alt) this.asset.store('alt', this.settings.alt);
		return this;
  },

	startup: function() {
		if(!this.started) {
			this.started = true;
			this.initAsset();
		}
	},

  initAsset: function() {
    //console.log('initAsset');
    this.chain(
      function () {
        //console.log('initAsset.chain fn 1: ', this.asset);
        seqImageLoader.addImage(this.asset.retrieve('image'), this);
			},

      function(img) {
        //console.log('initAsset.chain fn 2');
				if(this.asset.retrieve('alt')) img.set('alt', this.asset.retrieve('alt'));
				if(this.asset.retrieve('href')) {
					var link = new Element('a', {
						//href: this.asset.retrieve('href')
						href: 'javascript:void(0);'
					}).store('href', this.asset.retrieve('href')).adopt(img);
					this.asset.adopt(link);
				} else {
					this.asset.adopt(img);
				}
				this.callChain();
			},

			function() {
			  //console.log('initAsset.chain fn 3');
				if(this.asset.retrieve('fx') && this.asset.retrieve('morph')) this.asset.retrieve('fx').start(this.asset.retrieve('morph'));
				  else this.callChain();
			},

			function() {
			  //console.log('initAsset.chain fn 4');
				if(this.asset.retrieve('slide')) this.asset.retrieve('slide').slideIn();
				  else this.callChain();
			},

			function() {
			  //console.log('initAsset.chain fn 5');
				if(!this.callChain()) this.complete(this.asset);
			}
		)
		this.callChain();
	}
});