
var status_count = 2;


var column_count = 1;



var last_update = 0;
var update_every = 8000; // never update more than every x milliseconds


$(document).ready(function(){



	



	//lSet('project_data', '');
	
	last_update = current_ms_time();
	
	projects.retrieve();	
	
	$('a.save').live('click',function(){
	
		last_update = 0;
		projects.store();
	
	});
	
	// Add a project
	$('a.add_project').click(function(){	
		projects.add();	
		place_clears ();
	});
	
	// Add a task
	$('a.add_task').live('click',function(){
	
		var project_id = $(this).parents('div.project').attr('rel');
		
		projects.add_task(project_id);
		
		select($(this).parents('div.project').find('ul.tasklist li:last'));
		
		$(this).parents('div.project').find('ul.tasklist li:last').dblclick();
	
	});
	
	// Edit the project name
	set_project_dblclick_event();
	
	// Edit a tasklist name
	set_taskilst_dblclick_event();
	
	// Clicking/selecting a task list item
	$('.project ul.tasklist li').live('click',function(){
		select($(this));
	});
	
	// Delete a project
	$('a.delete_project').live('click', function () {
	
		var $proj = $(this).parents('div.project');
		var project_id = $proj.attr('rel');
		
		projects.del(project_id);
		
		$proj.remove();
		
		place_clears ();
	
	});
	
	// change a status
	$('span.status').live('click', function () {
	
		var $li = $(this).parents('li').eq(0);
		var status = $li.attr('status');
		status++;
		if (status >= status_count) {
			status = 0;
		}
		
		$li.attr('status',status);
		
		projects.edit($(this).parents('div.project').attr('rel'), 'tasks', tasks_from_ultasklist($(this).parents('ul.tasklist')) );
	
	});
	
	// Clear all data
	$('a.clear_data').click(function(){
	
		if (!confirm("Are you sure you want to clear all your data? It can't be undone and all your projects will disappear.")) {
			return false;
		}
		
		clear_fridge();
		
		
		
	
	});
	
	
	// Help box
	$('a.open_help').click(function(){
	
		lSet('show_help','more');		
		$('section#help .less').hide();
		$('section#help .more').fadeIn(250);
	
	});
	$('a.close_help').click(function(){
	
		lSet('show_help','less');		
		$('section#help .more').hide();
		$('section#help .less').show();
	
	});
	
	$('section#help .more, section#help .less').hide();
	
	if (lGet('show_help') == 'more') {
		$('section#help .less').hide();
		$('section#help .more').show();
	} else {
		$('section#help .more').hide();
		$('section#help .less').show();
		
	}
	
	
	// Delete by button click
	// Hide the delete button to begin with
	$('a.delete_task').live('click',function(){
		if ($(this).parents('.project').find('ul.tasklist li.selected').length > 0) {
			delete_current_task();
		}
	});
	
	
	
	

	// Key binding
	
	var keybinding_options = { "disable_in_input": true, "propagate": false };
	
	

	shortcut.add('Shift+n', function () {
		$('a.add_project').click();
		
	}, keybinding_options);

	shortcut.add('Space', function () {
		if ($('ul.tasklist li.selected').length > 0) {
			$('ul.tasklist li.selected').find('span.status').click();
		}		
	}, keybinding_options);

	shortcut.add('Delete', function () {
		if ($('ul.tasklist li.selected').length > 0) {
			delete_current_task();
		}		
	}, keybinding_options);

	shortcut.add('Up', function () {
		select_prev();
	}, keybinding_options);

	shortcut.add('Down', function () {
		select_next();
	}, keybinding_options);
	
	shortcut.add('Left', function () {
		select_prev_project();
	}, keybinding_options);
	
	shortcut.add('Right', function () {
		select_next_project();
	}, keybinding_options);
	
	shortcut.add('f2', function () {
		var $li = $('ul.tasklist li.selected');
		if ($li.length > 0) {
			$li.dblclick();
		}
	}, keybinding_options);
	
	shortcut.add('Insert', function () {
		var $li = $('ul.tasklist li.selected');
		if ($li.length <= 0) {
			select($li = $('ul.tasklist:first li:last'));
		}
		$li.parents('div.project').find('a.add_task').click();
		
	}, keybinding_options);
	
	
	 
	if ((document.location + '').search(/clear_fridge/) >= 0) {
		clear_fridge();
		document.location=app_info.url_site;
	}
	
	
	
	$(window).bind('beforeunload',function(){
		if (projects.changed && app_info.user.id) {
			return "There are changes that haven't been saved to the server. Are you sure you want to leave?";
		}
		
	});
	
	

});


function clear_fridge ()
{
	localStorage.clear();
	delete projects.database;
	$('#fl-container').empty();
}



function current_ms_time ()
{
	var date = new Date();
	return date.getTime();
	
}



function ajaxstatus (msg)
{
	msg = msg ? msg : '<span class="loading"></span> talking to server';
	$('#ajaxstatus').html(msg);
}





function place_clears ()
{
	var dw = $(document).width();
	
	if (dw > 950) {
		column_count = 3;
	
	} else if (dw > (950-303)) {
		column_count = 2;
	
	} else {
		column_count = 1;
	
	}
	
	$('div#fl-container div.project_seperator').remove();
	
	//console.log(column_count, $('div.project:nth-child('+column_count+'n)'));
	$('div.project:nth-child('+column_count+'n)').after('<div class="clr project_seperator">&nbsp;</div>');

	//alert('resizing');
}


function set_taskilst_dblclick_event ()
{
	$('.project ul.tasklist li').live('dblclick', function () {
		edit_task($(this));
	});
}


function set_project_dblclick_event ()
{
	$('.project header h4').live('dblclick', function () {
		edit_project_name($(this));
	});
}



function select_prev_project ()
{
	var $prev = $('ul.tasklist li.selected').parents('div.project').prev('.project');
	if ($prev.length <= 0) {
		select($('ul.tasklist:last li:last'));
	} else {
		select($prev.find('ul.tasklist li:first'));
	}
}
function select_next_project ()
{
	var $next = $('ul.tasklist li.selected').parents('div.project').next('.project');
	if ($next.length <= 0) {
		select($('ul.tasklist:first li:first'));
	} else {
		select($next.find('ul.tasklist li:first'));
	}
}
function select_next ()
{
	$sel = $('ul.tasklist li.selected');
	if ($sel.next().length <= 0) { 
		select($sel.parents('ul.tasklist').find('li:first'));
	} else {
		select($sel.next());
	}
}
function select_prev ()
{
	$sel = $('ul.tasklist li.selected');
	if ($sel.prev().length <= 0) { 
		select($sel.parents('ul.tasklist').find('li:last'));
	} else {
		select($sel.prev());
	}
}


function delete_current_task ()
{
	// Find the selected item, remove it from the list and save the list to the project database
	var $selected = $('ul.tasklist li.selected');	
	var project_id = $selected.parents('div.project').attr('rel');	
	var $ul = $selected.parents('ul.tasklist');	
	
	// if it's the last item, select the one next to it
	if ($selected.next().length <= 0) {
		select($selected.prev());
	} else {
		select_next();
	}
	
	
	$selected.remove();
	projects.edit(project_id, 'tasks', tasks_from_ultasklist($ul));
	
}

function select ($li)
{
	$('ul.tasklist li.selected').removeClass('selected');
	$li.addClass('selected');
	
	$('a.delete_task').hide();
	$li.parents('.project').find('a.delete_task').show().css({display:'inline-block'});
}

function edit_task ($li)
{	
	$('.project ul.tasklist li').die('dblclick');	
	$li.data('olddata', $li.find('span.name').html());

	var $input = $('<input type="text" value="" />').val($li.data('olddata'));
	
	$input.keydown(function(e){
	
		var $proj = $(this).parents('.project');
		var last = $(this).parents('li').next().length <= 0;
		
		if (e.keyCode == 13) { // enter key
			var ok = save_task(this);
			if (last && ok) {
				$proj.find('a.add_task').click();
			}
		} else if (e.keyCode == 27) { // escape key
		
			$li = $(this).parents('li');
			var val = $li.data('olddata');
			
			$li.find('span.name').html(val);
			set_taskilst_dblclick_event();
			
			
			if (val == '...' || !val) {
				select($li.prev());
				$li.remove();
				
				//delete_current_task ();
			}
			
			
		}		
		
	}).blur(function(){
		save_task(this);
		
	});
		
	$li.find('span.name').html($input);
	$input.select();
}



function save_task (input)
{
	var val = $(input).val();
	
	var $proj = $(input).parents('div.project');
	
	
	if (val == '...' || !val) {
		delete_current_task ();
		set_taskilst_dblclick_event ();
		return false;
	} else {

		var project_id = $proj.attr('rel');
		var $spanname = $(input).parents('span.name').html(val);
		
		
		projects.edit(project_id, 'tasks', tasks_from_ultasklist($spanname.parents('ul.tasklist')) );
		// If it's the last element in the list, let's add a new item
		set_taskilst_dblclick_event ();
		
		
		
		
		return true;
	}
	
	
	
	
	
}

function tasks_from_ultasklist ($ul)
{
	
	var collect = [];
	$ul.find('li').each(function(){
		collect.push({
			"name": $(this).find('span.name').html(),
			"status": $(this).attr('status')
		});
	});
	
	
	return collect;
}




function edit_project_name ($h4)
{

	$('.project header h4').die('dblclick');
	
	$h4.data('olddata', $h4.html());

	var $input = $('<input type="text" value="" />').val($h4.data('olddata'));
	
	$input.keydown(function(e){
	
		if (e.keyCode == 13) { // enter key
			save_project_name(this);
			
		} else if (e.keyCode == 27) { // escape key
			$h = $(this).parents('h4');
			$h.html($h.data('olddata'));
			
		}
		
		if (e.keyCode == 27 || e.keyCode == 13) {
			set_project_dblclick_event();		
		}
		
	}).blur(function(){
		save_project_name(this);
		
		set_project_dblclick_event();
	});
	
	
	
	$h4.html($input);
	
	$input.select();
}

function save_project_name(input)
{
	var $proj = $(input).parents('div.project');
	var project_id = $proj.attr('rel');
	var val = $(input).val();
	val = val.replace(">","&gt;").replace("<", "&lt;");
	projects.edit(project_id, 'name', val);
	$(input).parents('h4').html(val);			
	
	if ($proj.find('ul.tasklist').children().length <= 0) {
		$proj.find('a.add_task').click();
	}

}

var projects = {

	"database": {},
	"changed": false,
	
	"del": function (project_id) {
		delete projects.database[project_id];
		projects.store();
	},
	
	"edit": function (project_id, key, val) {
	
		var no_change = projects.database[project_id][key] == val;
		
		if (no_change || (val=='...'||!val) ) {
			//console.log('no change');
			return;
		} else {
			//console.log('change');
		}
		
		projects.database[project_id][key] = val;		
		projects.store();
	
	},
	
	"db_size": function () {
	
		var size = 0;
		for (key in projects.database) {
			//if (obj.hasOwnProperty(key)) size++;
			size++;
		}
		return size;
	},
	
	"add_task": function (project_id)
	{
		if (!project_id) { alert('Error: no project ID ???') }
		
		var new_t = {
			"name": "...",
			"status": 0
		};
		
		projects.database[project_id].tasks.push(new_t);
		
		$(".project[rel='"+project_id+"'] ul.tasklist").append(display_task(new_t));
		
		
		
	},
	
	"add": function ()
	{
		
		unix_timestamp = (new Date()).getTime() / 1000;
		
		var newid = generate_unique_id();
	
		var new_p = {
			"id": newid,
			"name": "Untitled",
			"created": unix_timestamp,
			"ordering": projects.db_size(),
			"tasks": []
		};
		
		projects.database[newid] = new_p;
		$('#fl-container').append(display_project(new_p));
		projects.store();
		
		
		edit_project_name ($('#fl-container .project:last').find('header h4'));
		
	},
	
	"retrieve": function () {
		
		projects.database = lGet('project_data');
		
		
		// If the user is logged in, let us grab some data
		if (app_info.user.id > 0) {
		
			$('#fl-container').html('<span class="loading"></span>');
		
			projects.retrieve_from_server(function(json){
			
				if (json.data) {
					
					var newdata = $.evalJSON(json.data);
					for (key in newdata) {
						if (!projects.database[key]) {
							projects.database[key] = newdata[key];
							
							
						}
						//console.log(key);
					}
					ajaxstatus('Data loaded.');
				} else {
					ajaxstatus('No data found...');
				}
			
				display_projects(projects.database);
				
			});
		
		} else {
			display_projects(projects.database);
		}	
		
	},
	
	"retrieve_from_server": function (callback) {
	
		ajaxstatus();
		$.ajax({
		
			url: app_info.url_app + '/user_list',
			dataType: 'json',
			success: callback,
			type: 'POST'
		
		});	
	
	},
	
	
	"store_on_server": function () {
	
		if (!app_info.user.id) {
			return;
		}
	
		projects.processing = true;
		
		
	
		ajaxstatus();
		
		$.ajax({
		
			url: app_info.url_app + '/save',
			dataType: 'json',
			success: function (json) {
				if (!json) return;
				if (!json.ok) {
					alert('Error saving: '+json.msg);
				}
				ajaxstatus('Data saved.');
				projects.changed = false;
				projects.processing = false;
				last_update = current_ms_time();
			},
			type: 'POST',
			data: {
				'data': $.toJSON(projects.database)
			}
		
		});
	
	
	},
	
	// Used for when the next update should be
	"timer": 0,
	
	// timer used for displaying the seconds until next save
	"ticker": 0,
	
	"store": function () {
		lSet('project_data', projects.database);
		
		projects.changed = true;
		
		ajaxstatus('Unsaved data, saving in <span class="num">'+Math.ceil(update_every/1000)+'</span> - <a class="save">Save now</a>');
		
		/*
			If the minimum time between updates has been reached and we're not in the
			middle of processing a requst, we can start storing on server.
			
			Else, we can store after the minimum amount of seconds.
			
			That way we prevent ever requesting more than every 5 seconds and we only
			request when we need to and when something has changed.
		*/
		clearTimeout(projects.timer);
		
		clearTimeout(projects.ticker);
		
		
		if ((last_update + update_every) < current_ms_time() && !projects.processing) {
			//console.log('Time constraints not met and were not processing anything');
			projects.store_on_server();			
		} else {			
			//console.log('Starting our timer');
			projects.timer = setTimeout(function() { projects.store_on_server(); }, update_every);
			
			projects.ticker = setInterval(function(){
				$('#ajaxstatus span.num').html(
					Number($('#ajaxstatus span.num').html()) - 1
				);
			}, 1000);
		}
		
		
	}
	
	
	
}

function lSet (key, value)
{
	return localStorage.setItem(key, $.toJSON(value));
}
function lGet (key, value)
{
	
	var val = localStorage.getItem(key);
	
	
	
	if (val) {
		val = $.evalJSON(val);
		
		return val;
		
	} else {
		return {};
	}
	
	
}


function display_projects (data)
{
	$('#fl-container').html('');
	$.each(data, function(){
	
		$('#fl-container').append(display_project(this));
		
	});
	
	// If the user resizes window, we'll want to replace the clearing divs for the right amount of columns
	$(window).resize(place_clears);
	place_clears();
	
}

function display_project (data)
{
	var $tpl_p = $($('#template_project').html());
	
	$tpl_p.attr('rel', data.id);
	
	$tpl_p.find('header h4').html(data.name);
	$tpl_p.find('header span.date').html(data.created);
	$tpl_p.find('ul.tasklist').html(display_tasks(data.tasks));
	$tpl_p.hide().fadeIn(100);
	return $tpl_p;
}

function display_tasks(data)
{
	var $buf = $('<div></div>');
	
	$.each(data, function(){
	
		$buf.append(display_task(this));
		
	
	});
	
	return $buf.html();
}

function display_task(data)
{
	var $tpl_t = $($('#template_task').html());
	
	$tpl_t.attr('status', data.status);
	$tpl_t.find('span.name').html(data.name);
	
	return $tpl_t;
	
}




//////////////////////////////////////////////////////////////////////
// Borrowed and edited from:
// http://mattsnider.com/languages/javascript/unique-id-generator/
// I edited out the code that keeps track of which ID has been added
//////////////////////////////////////////////////////////////////////

function generate_unique_id (charset, len, isNotInDOM) {
    var i = 0;
    if (! charset) {charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';}
    if (! len) {len = 32;}
    var id = '', charsetlen = charset.length, charIndex;

    // iterate on the length and get a random character for each position
    for (i = 0; len > i; i += 1) {
        charIndex = Math.random() * charsetlen;
        id += charset.charAt(charIndex);
    }


    return id;
};









