var Checklist = new Class({
	initialize: function() {
		window.addEvent('domready', this.setup.bind(this));
	},
	
	setup: function() {		
		this.chart = $('chart');
		var div = $$('div.template');
        
		this.template = div.getElement('li');
		div.dispose();

		this.updateProgress();
		
		if(!Browser.Engine.trident4)
			this.makeSortable();
		
		/*	Setup scroller (for when user drags items below view frame)	*/
		this.scroller = new Scroller(window);
		
		/*	Initialize the options for each item	*/
		$$('#checklist li').each(function(row) { this.initRow(row); }, this);
		
		/*  Initialize Bookmark	*/
		var bookmark = $$('.bookmark a')[0];
		if(bookmark)
			if(Browser.Engine.webkit)
				bookmark.set('text', 'Press ' + (Browser.Platform.mac ? 'CMD' : 'Ctrl') + '-D to Bookmark');
			else
				bookmark.addEvent('click', function(e) {
					e.stop();
					this.addBookmark(document.title, document.location.href);
				}.bind(this));

		/*	Do "placeholder" on the text	*/
		this.makePlaceholders();
		return this;
	},
	
	makePlaceholders: function() {
		var fields = $$('input[type=text]');
		fields.each(function(field) {
			if(Browser.Engine.webkit) {
				field.set('placeholder', field.value);
				field.set('value', '');
				return;
			}
			
			var form = field.getParent('form');

			form.addEvent('submit', function() {
				if(this.value === defaultValue)
					this.value = '';
			}.bind(field));

			var defaultValue = field.get('value');
			field.addEvents({
				'focus': function() {
					if(this.value === defaultValue)
						this.set('value', '').removeClass('placeholder');
				},
				'blur': function() {
					if(this.value.trim() === '')
						this.set('value', defaultValue).addClass('placeholder');
				}
			}).addClass('placeholder');
		});
	},
	
	makeSortable: function() {
		/*	Save each list (which will make a great droppable later!)	*/
		this.lists = $$('#checklist ul');

		/*	Create sortables from list items	*/
		var addTasks = $$('#checklist li')
								 .filter(	function(row) {
												var link = row.getElement('a');
												if(link && link.hasClass('add'))
													return row.setStyle('cursor', 'normal');
													// return true;
											});
		
		
		this.sortables = new Sortables(this.lists, {
			// handle:			'.move',
			revert:			true,
			snap:			10,
			opacity:		0.05,
			clone:			true,
			
			onStart:		function(row, clone) {
								this.scroller.start();
								this.sortables.drug = true;
								row.removeClass('selected');
				
								if(!Browser.Engine.trident)
									clone.addClass('drag');
																	
								clone.removeClass('selected')
									 .setStyle('width', row.getStyle('width'));
							}.bind(this),
							
			onComplete:		function(row, clone) {
								this.scroller.stop();

								if(!!this.sortables.drug)
									this.request(row.retrieve('move'));

								this.sortables.drug = false;
							}.bind(this)
		});
		this.sortables.removeItems(addTasks);
	},
	
	addBookmark: function(title, url){
		if(window.sidebar)	window.sidebar.addPanel(title, url,'');
		else
		if(document.all)	window.external.AddFavorite(url, title);
		else
		if(window.opera)
			var link = new Element('a', {
				'rel':		'sidebar',
				'target':	'_search',
				'title':	title,
				'href':		url
			}).inject($E('body')).click();
	},
	
	initRow: function(row) {
		/*	Iterate through all the links in the row	*/
		row.getElements('a').each(function(link) {
			/*	Store some pertinent data for each link to access	*/
			link.store(		'row',		row)
				.store(		'item',		row.getElement('.text'))
				.store(		'day',		link.getParent('ul'))
				.store(		'week',		link.getParent('div.week'));
			/*	Run the class-named function	*/
			link.addEvent(	'click',	function(event, link)	{
											if(event && event.stop)
												event.stop();
											this[link.getProperty('class')].run(link, this);
										}.bindWithEvent(this, link));
			/*	Store each link on the row	*/
			row.store(link.get('class'), link);
			row.store('item', link.retrieve('item'));
			link.retrieve('item', row).store(link.get('class'), link);
			
			/*	Let the Add Task function be a new page for IE6	*/
			if(Browser.Engine.trident4 && link.hasClass('add'))
				link.removeEvents();
				
		}, this);

		/*	If there's a task item in the row, add a "check" event to it	*/
		var item = row.getElement('.text'); 
		if(item) {
			row.getElement('input').addEvent('click', this.check.pass(item, this));
			var info = item.getNext('a');
			if(info)
				item.addEvent('click', info.fireEvent.pass('click', info));
		}
		
		return this;
	},
	
	move: function(link) {},
	
	check: function(item) {
		if(this.sortables.drug)
			return;
			
		item.toggleClass('removed');
		var input = item.getPrevious('input');
		input.checked = (item.hasClass('removed')) ? 'checked' : '';
		
		this.request(item.retrieve('move'));
		this.updateProgress();
		
		/*	Show More Info for clicked item, if not already	*/
		if(!item.getParent('li').hasClass('selected'))
			this.info(item.retrieve('info'));
	},
	
	add: function(link) {
		var row = this.template.clone().removeClass('template');
		row.inject(link.retrieve('row'), 'before');
		
        row.getElement('.item').set('html', '<input type="checkbox" /> <span class="text">Enter New Task Here...</span>');
		
		row.slide('hide')
		   .set('slide', {
				onComplete: function(row) {
					row.replaces(row.get('slide').wrapper);
					this.initRow(row)
						.edit(row)
						.updateProgress();
				}.bind(this)
			})
		   .slide('in');
	},
	
	remove: function(link) {
		var row = link.retrieve('row');

		var disposeAndUpdate = function() {
			row.dispose();
			this.updateProgress();
			this.request(link);
		}.bind(this);

		if(Browser.Engine.trident)
			disposeAndUpdate();
		else
			row.set('morph',	{
									duration:	'short',
									onComplete:	disposeAndUpdate
								})
			   .morph({ 'opacity': 0, 'height': 0 });

		return this;
	},
	
	edit: function(link) {
		if(link.get('tag') === 'li') link = link.retrieve('edit');
		var item = link.retrieve('item', link.getElement('.text'));
		var row = link.retrieve('row');
		var styles = $merge(item.getStyles('height','margin','padding','font-size','font-family'),
							{ 'font-weight': 'bold' });

		var input = new Element('input', {
			'value':	item.get('text').trim(),
			'styles':	styles,
			'events':	{
				
				blur: function() {
					var newValue = input.get('value').trim();
					var oldText = item.get('text').trim();
					item.set('text', newValue)
						.replaces(input);
												
					row.set('tween', { onComplete: row.removeProperty.pass('style', row) }).highlight();
					
					if(newValue == oldText)
						return false;
					
					this.request(link);
				}.bind(this),
				
				keypress: function(event) {
					switch(event.key) {
						case 'enter':
							this.fireEvent('blur');
							break;
					}
				}
			}
		}).setStyle('width', '320px');
		
		input.replaces(item);
		input.focus();
		input.select();
		
		return this;
	},
	
	info: function(link) {
		if(this.lastRow) this.lastRow.removeClass('selected').removeClass('progress');
		
		if(!link)
			return false;
		
		this.lastRow = link.retrieve('row').store('info', link);;
		
		this.collapseSidebar();
		
		new Request.HTML({
			onComplete: function(nodes, elements) {
				this.expandSidebar(nodes, elements);
			}.bind(this)
		}).get(link.getProperty('href'));
	},
	
	collapseSidebar: function() {
		var delay = 500;
		this.finishTime = new Date().getTime() + delay;
		
        this.lastRow.removeClass('selected').addClass('progress');

		var coords = {
			'side':	$('side-bar').getCoordinates($('checklist')),
			'link': this.lastRow.getCoordinates($('checklist'))
		};
		
		var source = coords.side.top;
		var destination = coords.link.top + (coords.link.height / 2);
		
		$('side-bar').set('morph', { duration: delay }).morph({
			'top':		[source, destination],
			'height':	0
		});
	},
	
	expandSidebar: function(nodes, elements) {
		var delay = this.finishTime - new Date().getTime();
		if(delay > 0) return this.expandSidebar.delay(delay, this, arguments);
		
		$('side-bar').empty()
					 .adopt(nodes)
  					 .setStyles({
						'visibility': 'hidden',
						'height': 'auto'
					 });
		
		/*	If there's a form on the page (electricity pricing), do post-back	*/
		var form = $('side-bar').getElement('form');
		if(form)
			form.addEvent('submit', function(event) {
				event.preventDefault();
				
				this.collapseSidebar();
				
				new Request.HTML({
					data: form.toQueryString(),
					onComplete: function(nodes, elements) {
						this.expandSidebar(nodes, elements);
					}.bind(this)
				}).get(form.action);
			}.bind(this));

		/*	Do expansion	*/
		var coords = {
			'side':			$('side-bar').getCoordinates($('checklist')),
			'link':			this.lastRow.removeClass('progress')
										.addClass('selected')
										.getCoordinates($('checklist'))
		};
		
		var source = coords.link.top + (coords.link.height / 2);
		var destination = source - (coords.side.height / 2);
			
		$('side-bar').morph({
			'top':		[source, (destination < 0) ? 0 : destination],
			'height':	[0, coords.side.height]
		}).setStyles({
			'height':		0,
			'visibility':	'visible'
		});
	},
	
	hideOverview: function() {
		$('overview').set('tween', {
						'duration':	'long',
						'onComplete': function() {
							$('overview').dispose();
						}
					  })
					 .tween('opacity', 0);
	},
	
	updateProgress: function() {
		if(!existingUser) return false;
		
		var overdue = $$('#checklist .overdue input').filter(function(input) {
						return !input.getProperty('checked');
					  }).length;
		var total = $$('#checklist input[type=checkbox]').length;
		var data = "chd=t:"
				 + overdue
				 + ","
				 + (completed = $$('#checklist input[checked]').length)
				 + ","
				 + (uncompleted = (total - completed));
		
		$$('.overdue .items').set('text', overdue).getParent('li').setStyle('display', overdue ? 'block' : 'none');
		$$('.total .items').set('text', total);
		$$('.completed .items').set('text', completed);
		$$('.uncompleted .items').set('text', uncompleted);
				
		new Asset.image(this.chart.src.replace(/chd=[^&]+/, data), {
			onabort: function() { this.dispose(); },
			onload:	function(img) {
				img.inject(this.chart, 'before');
				this.chart.set('tween', { onComplete: this.chart.dispose.bind(this.chart) })
						  .fade('out');
				this.chart = img;	
			}.bind(this)
		});

		this.collapseCompleted();

		return this;
	},
	
	collapseCompleted: function() {
		$$('#checklist ul').each(function(list) {
			var unchecked = list.getElements('input').filter(function(input) {
				return !input.getProperty('checked');
			}).length;
			
			var div = list.getParent('div');
			
			if(div.id === 'side-bar') return;
			
			(unchecked)	?	div.removeClass('completed')
						:	div.addClass('completed');
		});
	},
	
	request: function(link, className) {
		this.collapseCompleted();
		
		var args = $A(arguments).link({
			'link':			Element.type,
			'className':	String.type
		});
		
		var data = {};
		
		if(!args.className) args.className = link.get('class');
		
		switch(args.className) {
			case 'edit':
				data.text = args.link.retrieve('item').getProperty('text');
				data.week = args.link.retrieve('item').getParent('ul').get('id').replace('week_', '');
				break;
			case 'move':
				data.order = this.saveOrder();
				break;
		}
			
		new Request.HTML({
 			'url':			link.getProperty('href'),
			'onComplete':	function(nodetree, elements) {
								if(!elements.length) return false;
								var row = elements[0].replaces(link.retrieve('row'));
								this.initRow(row);
								if(this.sortables)
									this.sortables.addItems(row);
							}.bind(this)
		}).post({'data': data});
	},
	
	saveOrder: function() {
		var weeks = {};
		this.sortables.serialize(function(element, index) {
			var id = element.getProperty('id');
			if(!id) return false;
			
			var week = element.getParent().getProperty('id').replace('week_', '');

			if(!weeks[week]) weeks[week] = {};
			
			var checked = !!element.getElement('input').getProperty('checked');

			weeks[week][id.replace('task_', '')] = Number(checked);
		});
		
		return JSON.encode(weeks);
	}
});

