/*
 * add a new project
 */
fn.project.add = function(options) {
	var settings = {
			divider : false
		};

	settings = $.extend(settings, options);
		
	fn.global.unedit();

	// clone the tempate and give it an id
	var id = '_' + fn.functions.uniqId();

	project = {
		id : id,
		divider: settings.divider
	};

	fn.project.populate(project, {
		edit : true,
		prepend : true
	});
	
	fn.view.bubble(fn.global.bubbles.firstProject);
	delete fn.global.bubbles.firstProject;
};

/**
 * get project as object 
 * this = project
 */
fn.project.toObject = function() {
	var $project = $(this);
	var title = $('h3 .label', $project).text();
	title = fn.functions.htmlEncode(title);

	var comment = $('.comment span', $project).html();
	comment = fn.functions.link2Url(comment);
	comment = fn.functions.htmlEncodeMultiline(comment, '<br *\/*>\n*', '<br />', 'gi');
	
	if ( !$project.hasClass('_divider') )
	{
		var header = $project.prevAll('._divider').attr('id');
	};

	var project = {
		id 			: $project.attr('id'),
		title 		: title,
		state 		: $('.selected', $project).attr('data-id'),
		scheduled 	: $('.schedule', $project).val(),
		comment 	: comment,
		divider		: $project.hasClass('_divider'),
		header		: header
	};

	return project;
};

/**
 * Change the project state
 */
fn.project.state = function(e) {
	fn.global.unedit();

	// get clicked and make sure it's an anchor
	var clicked = $(e.target);
	if (clicked.is(':not(a)'))
	{
		return;
	};

	// get variables
	var project = clicked.closest('.project');
	var prev = $('.states .selected', project);
	var prevId = prev.attr('data-id');
	if (undefined === prevId) 
	{
		prevId = '';
	};
	var nextId = clicked.attr('data-id');

	// add remove the state as a class
	project.removeClass(prevId).addClass(nextId);

	// update states' classes
	$(prev).removeClass('selected');
	clicked.addClass('selected');

	// update project's state flag
	$('.state', project).text(clicked.text()).css( {
		backgroundColor : clicked.css('backgroundColor')
	});

	// show comment and make it editable
	$('.comment', project).removeClass('hidden');
	fn.project.editComment.call($('.comment span', project));

	fn.account.save();
};

/**
 * Make h3 of project editable
 */
fn.project.editH3 = function() {
	fn.global.unedit();

	// set 'title' to send into event functions
	var $title = $(this);

	var $project = $title.closest('.project');
	var isDivider =  $project.hasClass('_divider');

	// get currect value
	var text = $title.text();
	var text = fn.functions.htmlEncode(text);

	// new input element
	switch( isDivider )
	{
	case true:
		var label = 'Header name';
		break;
	default:
		var label = 'The item\'s name';
	}
		
	var id = fn.functions.uniqId();
	var $html = $('<label for="_' + id + '">' 
		+ label + ':</label> <input type="text" name="title" id="_'
		+ id + '" value="' + text + '" class="editing" maxlength="56" />');

	// replace html and assign save actions
	$title.html($html)
	.find('input:first')
	.attr('data-original', text)
	.keyup(function(e) {
		// on escape, restore prev value
		if (e.keyCode == 27) 
		{
			restoreOrig.call(this);
			return false;
		};
		
		// on 'enter' key, set and save value
		if (e.keyCode == 13) 
		{
			saveEdit.call(this);
			return false;
		};
	})
	.blur(function(e) {
		saveEdit.call(this);
	})
	.focus();
	
	fn.global.refreshRemove();
	
	// save edit function
	function saveEdit() {
		// get text
		var text = $(this).val();
		text = fn.functions.htmlEncode(text);
		text = fn.functions.url2Link(text);

		if ( isDivider && '' === text)
		{
			text = '&bull;';
		};

		// if empty, remove project
		if ('' === text) 
		{
			fn.project.remove.call($project);
			return false;
		};

		// insert our text and save
		$title.html(text);
		fn.account.save();
		
		fn.view.bubble(fn.global.bubbles.newState);
		delete fn.global.bubbles.newState;
		
		$('#newState').removeClass('hidden');
	};
	
	// restore orig val
	function restoreOrig() {
		var text = $(this).attr('data-original');
		text = fn.functions.url2Link(text);
		
		// if previous is empty, remove project
		if ('' === text) 
		{
			fn.project.remove.call($project);
			return false;
		};

		$title.html(text);
	};
};

/**
 * make comment editable
 */
fn.project.editComment = function() {
	fn.global.unedit();

	// set 'span' to send into event functions
	var $span = $(this);

	// get currect value (get val if already editing)
	var text = ($('textarea', $span).length > 0) ? $('textarea', $span).val() : $span.html();
	text = fn.functions.link2Url(text);
	text = fn.functions.htmlEncodeMultiline(text, '<br *\/*>\n*', '\n', 'gi');

	// new input element
	var id = fn.functions.uniqId();
	var $html = $('<label for="_'
			+ id
			+ '">Add some notes: (URL\'s will become links)</label> <textarea id="_'
			+ id + '" class="editing">' + text + '</textarea>');

	// replace text w html form, add events
	$span
	.html($html)
	.find('textarea:first')
	.attr('data-original', text)
	.keyup(function(e) {
		// on escape, restore prev value
		if (e.keyCode == 27) 
		{
			restoreOrig.call(this);
			return false;
		};
		
		// shift + enter saves
		if (e.shiftKey == 1 && e.keyCode == 13) {
			saveEdit.call(this);
			return false;
		};
	})
	.blur(function(e) {
		saveEdit.call(this);
	})
	.focus()
	.autoResize( {
		animateDuration : 0,
		extraSpace : 0
	})
	.keyup()
	.select();
	
	fn.global.refreshRemove();
	
	// save edit function
	function saveEdit() {
		// get text
		var text = $(this).val();
		text = fn.functions.htmlEncodeMultiline(text, '\n\r|\r|\n', '<br />', 'gi');
		text = fn.functions.url2Link(text);

		// if there's no comment, hide the comment element
		if ('' === text)
		{
			$(this).parents('.comment').addClass('hidden');
		};

		$span.html(text);
		fn.account.save();
		
		fn.view.bubble(fn.global.bubbles.firstCompleted);
		delete fn.global.bubbles.firstCompleted;
		
		$('#' + fn.global.view + 'StatesList a.hidden:not(.scheduled), #newItem, #newState, #newDivider').removeClass('hidden');
	};
	
	// restore orig val
	function restoreOrig() {
		var text = $(this).attr('data-original');
		text = fn.functions.n2Br(text);
		text = fn.functions.url2Link(text);
		
		// if there's no comment, hide the comment element
		if ('' === text)
		{
			$(this).parents('.comment').addClass('hidden');
		};

		$span.html(text);
	};
};

/**
 * Add a project to the DOM
 * 
 * project = { id : $(this).attr('id'), title : $('h3 .label', this).text(),
 * state : $('.selected', this).attr('title'), comment : $('.comment span',
 * this).html() }
 * 
 * options: edit (make h3 editable) prepend {put new project first, not last}
 */
fn.project.populate = function(project, options) {
	var settings = {
		edit : false,
		prepend : false
	};

	settings = $.extend(settings, options);

	// clone the template html
	var $html = $('#templates .project').clone(true);
	
	if ( project.divider )
	{
		$html.addClass('_divider');
		$('ul.states', $html).remove();
		$('.state', $html).remove();
		$('.scheduleLi', $html).remove();
	};

	if ( undefined !== project.scheduled && '' !== project.scheduled )
	{
		var projectScheduled = new Date(project.scheduled);

		if ( projectScheduled.valueOf() >= fn.global.today.valueOf() )
		{
			$html.addClass('scheduled');

			$('h3', $html).prepend('<span class="date">Scheduled: <b>' + fn.functions.friendlyDate(projectScheduled) + '</b></span>');
			$('input.schedule', $html).val(project.scheduled);
			fn.state.scheduledCount(1);
		};
	}
	else
	{
		$('input.schedule', $html).val('');
	};
	
	$('input.schedule', $html).attr('id', '_' + fn.functions.uniqId());

	// give it an ID
	$html.attr('id', project.id);

	// add it to the DOM
	if (settings.prepend) 
	{
		// if it was saved under a header, try to put it under that header
		if ('' != project.header && $('#' + project.header).length > 0 ) 
		{
			$html.insertAfter('#' + project.header);
		}
		else
		{
			$html.prependTo('#projectsList');
		};
	} 
	else 
	{
		$html.appendTo('#projectsList');
	};
	
	fn.project.applyDatepicker.call($html);

	// add the h3 title
	project.title = fn.functions.url2Link(project.title);
	$('h3 .label', $html).html(project.title);

	// make the title editable
	if (settings.edit) {
		fn.project.editH3.call($('h3 .label', $html));
	};

	// set the current state
	var selected = $('.states a[data-id=' + project.state + ']', $html).addClass('selected');
	$html.addClass(project.state);

	// flag text
	var stateText = selected.text();

	// set flag text
	$('.state', $html).text(stateText).css( {
		backgroundColor : selected.css('backgroundColor')
	});

	// add comment
	if (undefined !== project.comment && project.comment.length > 0) 
	{
		var comment = $('.comment', $html);
		comment.removeClass('hidden');
		project.comment = fn.functions.url2Link(project.comment);
		$('span', comment).html(project.comment);
	};
	
	fn.projects.empty();
};

/**
 * remove a project
 * this = project
 */
fn.project.remove = function() {
	if ( $(this).hasClass('scheduled') )
	{
		fn.state.scheduledCount(-1);
	};
	
	fn.project.ghost.call(
		this, 
		'Your item has been removed.', 
		function(){
			$(this).remove();
		}
	);
};

/**
 * replace project with notification li
 * this = project
 */
fn.project.ghost = function(message, callback){
	if ( undefined == callback )
	{
		callback = function(){
			$(this).remove;	
		};
	};
	
	var $scheduled = $('<li class="ghost"><h3>' + message + '</h3></li>');

	$scheduled
	.css({
		height: $(this).height()
	})
	.insertBefore(this);

//	$(this).slideUp(function() {
		callback.call(this);
		fn.account.save();
		fn.projects.empty();
//	});
	
	setTimeout(function(){
		$scheduled.fadeOut(function(){
			$scheduled.remove();
			fn.projects.empty();
		});
	}, 3000);
};

/**
 * schedule a project
 * this = project
 */
fn.project.schedule = function() 
{
	var projectScheduled = new Date( $('input.schedule', this).val() );

	if ( $(this).hasClass('scheduled') )
	{
		$('h3 span.date', this).html('<span class="date">Scheduled: ' + fn.functions.friendlyDate(projectScheduled) + '</span>');
		fn.account.save();
		return;
	};
	
	$('h3', this).prepend('<span class="date">Scheduled: ' + fn.functions.friendlyDate(projectScheduled) + '</span>');
	
	fn.state.scheduledCount(1);
	
	fn.project.ghost.call(
		this, 
		'Your item has been scheduled.', 
		function(){
			$(this)
			.addClass('scheduled')
			.hide();
		}
	);
};

/**
 * remove project from scheduled items
 * this = project
 */
fn.project.unschedule = function() 
{
	fn.state.scheduledCount(-1);

	$(this).removeClass('scheduled');
	$('input.schedule', this)
	.val('')
	.dpClearSelected();
	
	$('h3 span.date', this).remove();

	fn.project.ghost.call(
		this, 
		'Your item has been unscheduled.', 
		function(){
			$(this)
			.removeClass('scheduled')
			.hide();
		}
	);
};

/**
 * apply datepicker
 * this = project
 */
fn.project.applyDatepicker = function() 
{
	var $project = $(this);
	
	var tomorrow = new Date().addDays(1);

	$('input.schedule', $project).datePicker({
		startDate : tomorrow.asString() // format matches global Date format
	})
	.bind('dateSelected', function() {
		fn.project.schedule.call($project);
	})
	.bind('dpDisplayed', function(event, datePickerDiv) {

		if ( $project.hasClass('scheduled') )
		{
			$('<p class="unscheduleWrapper">Or <a href="#" class="unschedule">Unschedule this item?</a></p>')
			.appendTo(datePickerDiv);

			$('a.unschedule', datePickerDiv).click(function(){
				fn.project.unschedule.call($project);
				$('#dp-popup').remove();
			});
		};	
	});
};

/**
 * Check if the projects list is full/empty, and show/hide a message
 */
fn.projects.empty = function(message) 
{
	$('#empty').remove();
	
	if ( undefined === message )
	{
		message = '';
	};
	
	if ( 0 == $('#' + fn.global.view + 'List li:visible').length ) 
{
		$('<li id="empty">There are no items ' + message + '</li>').prependTo(
				'#' + fn.global.view + 'List');
//		$('#newState, #newDivider, #' + fn.global.view + 'StatesList').addClass('hidden');
	} 
	else 
	{
		$('#empty').remove();
	};
};

/**
 * filter projects by state clicked
 */
fn.projects.filter = function() {
	// get clicked and ignore if already selected
	var $clicked = $(this.target);
	var $clicked = $clicked.closest('a');
	if ($clicked.is(':not(a), .selected')) 
	{
		return;
	};
	
	$('#projectsList > li.ghost').remove();

	var filterList = $clicked.closest('.filterList');

	// set selected flag on correct state
	$('.selected', filterList).removeClass('selected');
	$clicked.addClass('selected', this);

	// show all
	if ($clicked.is('.all')) 
	{
		$('#projectsList > li.scheduled').hide();
		$('#projectsList > li:not(.scheduled)').show();
		$('#newItem, #newDivider').show();
		fn.projects.empty();
		return;
	};

	// show all
	if ($clicked.is('.scheduled')) 
	{
		$('#projectsList > li:not(.scheduled)').hide();
		$('#projectsList > li.scheduled').show();
		$('#newItem, #newDivider').hide();
		fn.projects.empty('scheduled');
		return;
	};
	
	// filter projects
	$('#projectsList > li:not(.' + $clicked.attr('id') + ')').hide();
	$('#projectsList > li.' + $clicked.attr('id')).show();
	
	fn.global.refreshReset();
	fn.projects.empty('marked as &quot;' + $clicked.text() + '&quot;');
};

fn.projects.checkScheduled = function() {
	$('#' + fn.global.view + 'List .scheduled').each(function(){
		var projectScheduled = new Date( $('.schedule', this).val() );

		if (projectScheduled.valueOf() <= fn.global.today.valueOf()) 
		{
			$(this).removeClass('scheduled');
			fn.state.scheduledCount(-1);
		};
	});
};
