/*
 * 
 * Find more about this app by visiting
 * http://miniapps.co.uk/
 *
 * Copyright (c) 2010 Alex Gibson, http://miniapps.co.uk/
 * 
 */

var checklistApp = (function() {

	var myScroll,
		lastItemAdded = '',
		itemAdded = true,
		isIpad = (/ipad/gi).test(navigator.appVersion),
		isIphone = (/iphone/gi).test(navigator.appVersion),
		isIpod = (/ipod/gi).test(navigator.appVersion),
		isAndroid = (/android/gi).test(navigator.appVersion),
		isBlackberry = (/blackberry/gi).test(navigator.appVersion),
		isMobile = ((isIpad) || (isIphone) || (isIpod) || (isAndroid) || (isBlackberry)),
		hasTouch = ((('ontouchstart' in window) || ('createTouch' in document)) && (isMobile)),
		isStandalone = (("standalone" in window.navigator) && (window.navigator.standalone)),
		supportsLocalStorage = (('localStorage' in window) && (window['localStorage'] !== null)),
		headerHeight = 45,
        footerHeight = 44,
        wrapperHeight = 0,
        itemsOnScreen = 0,
        listItemHeight = 44,
        total = 0,
        completed = 0;

	return {

		//get all items and displays the list
		getAllItems: function() {

			var containerNode = document.querySelector('#scroller'),
				listNode = document.querySelector('#checklist'),
				frag = document.createDocumentFragment(),
				checklist,
				myArray = [],
				listLength = localStorage.length-1,
				item = '',
				itemName = '',
				itemValue = '',
				i = 0,
				j = 0,
				k = 0;
				
			total = 0;
			completed = 0;

			//get all items from localStorage and sort alphabetically
			for (i = 0; i <= listLength; i++) {
			
				item = localStorage.key(i);
				myArray.push(item);
			}

			myArray.sort();
			
			containerNode.removeChild(listNode);
			checklist = document.createElement('ul');
			checklist.setAttribute('id', 'checklist');
			checklist.setAttribute('role', 'list');
			containerNode.appendChild(checklist);
			
			//create list and then insert HTML
			for (j = 0; j <= listLength; j++) {

				itemName = myArray[j],
				itemValue = localStorage.getItem(itemName);

				//check item is not temporary (i.e. stored on key-up from user input)
				if (itemName !== 'inputvalue') {
				
					var newItem = document.createElement('li'),
						checkbox = document.createElement('input'),
						itemLabel = document.createElement('label'),
						editButton = document.createElement('div');

					//is the item checked
					if (itemValue === '1') {
					
						var newItem = document.createElement('li'),
							checkbox = document.createElement('input'),
							itemLabel = document.createElement('label'),
							editButton = document.createElement('div');
						
						newItem.setAttribute('role', 'listitem');
						
						checkbox.setAttribute('type', 'checkbox');
						checkbox.setAttribute('checked', 'true');
						
						itemLabel.setAttribute('class', 'done');
						
						editButton.setAttribute('class', 'edit');
						editButton.setAttribute('role', 'button');
						editButton.setAttribute('aria-labelledby', 'edit_label');
						editButton.setAttribute('tabindex', '0');

						if (itemName === lastItemAdded) {
						
							newItem.setAttribute('id', 'highlight');	
						}

						frag.appendChild(newItem);
						newItem.appendChild(checkbox);
						newItem.appendChild(itemLabel);
						newItem.appendChild(editButton);
						itemLabel.innerHTML = itemName;
						
						total++;
						completed++;
					}
					else if (itemValue === '0') {
					
						var newItem = document.createElement('li'),
							checkbox = document.createElement('input'),
							itemLabel = document.createElement('label'),
							editButton = document.createElement('div');
						
						newItem.setAttribute('role', 'listitem');
						
						checkbox.setAttribute('type', 'checkbox');
						
						editButton.setAttribute('class', 'edit');
						editButton.setAttribute('role', 'button');
						editButton.setAttribute('aria-labelledby', 'edit_label');
						editButton.setAttribute('tabindex', '0');
					
						if (itemName === lastItemAdded) {
						
							newItem.setAttribute('id', 'highlight');	
						}
						
						frag.appendChild(newItem);
						newItem.appendChild(checkbox);
						newItem.appendChild(itemLabel);
						newItem.appendChild(editButton);
						itemLabel.innerHTML = itemName;
						
						total++;
					}
				}
				else {
					document.querySelector('#name').value = itemValue;
				}
			}
			
			//list is empty
			if (total === 0) {
			
				var arrow = document.createElement('li');
				
				arrow.setAttribute('class', 'empty');
				arrow.innerHTML = '<span id="arrow">&uarr;</span>';
				checklist.appendChild(arrow);
				
				var itemText = document.createElement('li');
				
				itemText.setAttribute('class', 'empty');
				itemText.innerHTML = 'Add an item to get started.';
				checklist.appendChild(itemText);
			}
			else {
			
				var totalBar = document.createElement('li'),
					totalValue = document.createElement('span'),
					remainingValue = document.createElement('span');
					
				totalBar.setAttribute('id', 'total-bar');
				totalBar.appendChild(totalValue);
				totalBar.appendChild(remainingValue);
				
				totalValue.setAttribute('id', 'total-value');
				totalValue.innerHTML = 'Total: ' + total;
				
				remainingValue.setAttribute('id', 'remaining-value');
				remainingValue.innerHTML = 'Remaining: ' + (total - completed);
			
				document.querySelector('#checklist').appendChild(totalBar);
				document.querySelector('#checklist').appendChild(frag);
			}			
			
			//scroll to last item added only if list is longer than height of visible scrolling layer
			if (lastItemAdded !== '') {
					
				if (hasTouch) {	
					
					if (total > itemsOnScreen) {
						
						setTimeout(function () { myScroll.refresh(); myScroll.scrollToElement('#highlight', 300); }, 0);
					}
				}
				lastItemAdded = '';
			}
			else if (hasTouch) {
                setTimeout(function () { myScroll.refresh() }, 0);
			}
			
			checklistApp.eventDelegation();
			
			//update mail button link
			checklistApp.updateMail();	
		},
				
		deleteItem: function() {
		
			var item = document.querySelector('#original-name').value;
			
			if(confirm('Are you Sure?')) {
			
				localStorage.removeItem(item);
				checklistApp.getAllItems();
				document.querySelector('#list').setAttribute('aria-hidden', 'false');			
				if (hasTouch) {
					myScroll = new iScroll('wrapper');
				}
				
				document.getElementById('delete').blur();
				document.querySelector('#edit').setAttribute('aria-hidden', 'true');
				
			}
			else {
				document.getElementById('delete').blur();
			}
		},
		
		//check key press
		keyDeleteItem: function(e) {
		
			if ((e.keyCode === 13) || (e.keyCode === 32)) {
				checklistApp.deleteItem();
			}
		},
		
		//save edited item and return to list
		saveItem: function(e) {
		
			e.preventDefault();
		
			var editedItem = document.querySelector('#edit-field').value,
				strippedString = editedItem.replace(/&/g,'&amp;').replace(/<([^>]+)>/g,'').replace(/</g,'&lt;').replace(/>/g,'&gt;'), //remove tags
				originalItem = document.querySelector('#original-name').value,
				data = 0;
				
			if (strippedString !== '') {
				
				if (document.querySelector('#edit-completed').checked) {
					data = 1;
				}
				else {
					data = 0;
				}
							
				try {
					localStorage.removeItem(originalItem);
					localStorage.setItem(strippedString, data);
					
					document.querySelector('#edit-field').blur();
				} 
				catch (error) {
			
					if (error === QUOTA_EXCEEDED_ERR) {
						alert('Quota exceeded!');
					}
				}
				
				if ((data === 0) && (strippedString !== originalItem)) {
					lastItemAdded = strippedString;
				}
				else {
					lastItemAdded = '';
				}
				
				checklistApp.getAllItems();
				
				document.querySelector('#delete').removeEventListener('click', checklistApp.deleteItem, false);
				document.querySelector('#delete').removeEventListener('keydown', checklistApp.keyDeleteItem, false);
				document.querySelector('#editform').removeEventListener('submit', checklistApp.saveItem, true);
			
				document.querySelector('#list').setAttribute('aria-hidden', 'false');
			
				if (hasTouch) {
					myScroll = new iScroll('wrapper', { useTransition:true });
				}
			
				document.querySelector('#edit').setAttribute('aria-hidden', 'true');
			}
			else {
				document.querySelector('#edit-field').value = originalItem;
				document.querySelector('#edit-field').blur();
			}	
		},
		
		//show edit screen
		editItem: function(itemName, itemValue) {
		
			var replacedString = itemName.replace(/&amp;/g,'&').replace(/<([^>]+)>/g,'').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
	
			document.querySelector('#edit').setAttribute('aria-hidden', 'false');
			
			if (hasTouch) {
				myScroll.destroy();
			}
			
			document.querySelector('#list').setAttribute('aria-hidden', 'true');
			
			document.querySelector('#original-name').value = itemName;
			
			if (itemValue === 1) {
				document.querySelector('#edit-completed').checked = true;
			}
			else if (itemValue === 0) {
				document.querySelector('#edit-completed').checked = false;
			}
			
			document.querySelector('#edit-field').value = replacedString;
			
			document.querySelector('#delete').addEventListener('click', checklistApp.deleteItem, false);
			document.querySelector('#delete').addEventListener('keydown', checklistApp.keyDeleteItem, false);
			document.querySelector('#editform').addEventListener('submit', checklistApp.saveItem, true);
		},

		//capture click events in list
		eventDelegation: function() {

			var listitems = document.querySelector('#checklist');
	
			listitems.onclick = function (e) {
	
				var name = '',
					data = 0,
					element = e.target,
					remainingValue = document.querySelector('#remaining-value');
			
				//<label>
				switch(element.tagName.toLowerCase()) {
					
					case 'label':
		
						name = element.innerHTML;
			
						if (element.previousSibling.checked) {
						
							data = 0;
							element.previousSibling.checked = false;
							element.className = '';
							completed--;
						}
						else {
						
							data = 1;
							element.previousSibling.checked = true;
							element.className = 'done';
							completed++;
						}

						try {
						
							localStorage.setItem(name, data);
							remainingValue.innerHTML = 'Remaining: ' + (total - completed);
							//update mail button link
							checklistApp.updateMail();
						} 
						catch (err) {
			
							if (err === QUOTA_EXCEEDED_ERR) {
								alert('Quota exceeded!');
							}
						}
						break;
						
					case 'input': 
		
						name = element.nextSibling.innerHTML;
				
						if (element.checked) {
						
							data = 1;
							element.checked = true;
							element.nextSibling.className = 'done';
							completed++;
						}
						else {
						
							data = 0;
							element.checked = false;
							element.nextSibling.className = '';
							completed--;
						} 

						try {
						
							localStorage.setItem(name, data);
							remainingValue.innerHTML = 'Remaining: ' + (total - completed);
							//update mail button link
							checklistApp.updateMail();
						} 
						catch (error) {
			
							if (error === QUOTA_EXCEEDED_ERR) {
								alert('Quota exceeded!');
							}
						}
						break;
						
					case 'div':
					
						name = element.previousSibling.innerHTML;
						
						if (element.previousSibling.previousSibling.checked) {
							data = 1;
						}
						else {
							data = 0;
						}
						
						checklistApp.editItem(name, data);
						break;
				}
			};
			
			listitems.onkeydown = function(e) {
			
				switch(e.keyCode) {
				
					case 32:
					
						if (e.target.tagName.toLowerCase() === 'div') {
						
							name = e.target.previousSibling.innerHTML;
						
							if (e.target.previousSibling.previousSibling.checked) {
								data = 1;
							}
							else {
								data = 0;
							}
						
							checklistApp.editItem(name, data);
						}
						break;
						
						
					case 13:
					
						if (e.target.tagName.toLowerCase() === 'div') {
						
							name = e.target.previousSibling.innerHTML;
						
							if (e.target.previousSibling.previousSibling.checked) {
								data = 1;
							}
							else {
								data = 0;
							}
						
							checklistApp.editItem(name, data);
						}
						break;
				}
			
			};
		},

		//adds a single item
		addNewItem: function() {
	
			var name = document.querySelector('#name').value,
				data = 0,
				strippedString = name.replace(/&/g,'&amp;').replace(/<([^>]+)>/g,'').replace(/</g,'&lt;').replace(/>/g,'&gt;'); //remove tags
		
			//add item
			if (strippedString !== "") {
	
				try {
					localStorage.setItem(strippedString, data);
					
					//item to auto scroll to if iscroll is enabled
					lastItemAdded = strippedString;
					document.querySelector('#name').blur();
				} catch (e) {
					if (e === QUOTA_EXCEEDED_ERR) {
						alert('Quota exceeded!');
					}
				}
				//clear the input value
				document.querySelector('#name').value = "";
				//remove temporary item from storage
				localStorage.removeItem('inputvalue');
                checklistApp.getAllItems();
			}
			else {
				document.querySelector('#name').blur();
				itemAdded = false;
			}
		},

		//delete all checked items
		deleteChecked: function() {

			if (confirm("Delete checked items?")) {

				var i = 0,
					length = localStorage.length - 1;
			
				while (i <= length) {
		
					var key = localStorage.key(i);
					if (localStorage.getItem(key) === '1') {
						localStorage.removeItem(key);
						length--;
					}
					else { i++; }
				}
				lastItemAdded = '';
            	checklistApp.getAllItems();
            	
            	document.getElementById('deletechecked').blur();
            }
            else {
            	document.getElementById('deletechecked').blur();
            }
		},
		
		//delete all items
		keyDeleteChecked: function(e) {
		
			if ((e.keyCode === 13) || (e.keyCode === 32)) {
				checklistApp.deleteChecked();
			}
		},

		//delete all items
		deleteAll: function() {
		
			var length = localStorage.length -1;

			if (confirm("Delete all items?")) {
			
				localStorage.clear();
				
				for (i = 0; i <= length; i++) {
		
					key = localStorage.key(i);
			
					//delete localstorage item if a checklist item
					if ((localStorage.getItem(key) === '0') || (localStorage.getItem(key) === '1')) {
						localStorage.removeItem(key);
					}
				}
				
				lastItemAdded = '';
				checklistApp.getAllItems();
				document.getElementById('deleteall').blur();
				document.querySelector('#maillink').href = 'mailto:';		
			}
			else {
				document.getElementById('deleteall').blur();
			}
		},
		
		//check key press
		keyDeleteAll: function(e) {
		
			if ((e.keyCode === 13) || (e.keyCode === 32)) {
				checklistApp.deleteAll();
			}
		},

		//updates the URL in mail items buttons
		updateMail: function() {
	
			var mail = 'mailto:?',
				subject = 'My list',
				list = '',
				length = localStorage.length -1,
				key = 0,
				i = 0;
	
			if (length >= 0) {
	
				for (i = 0; i <= length; i++) {
		
					key = localStorage.key(i);
			
					//append to list if not checked
					if (localStorage.getItem(key) === '0') {
						list += localStorage.key(i) + '\n';
					}
				}
				//update mail link
				if (list !== '') {
					mail += 'subject=' + encodeURIComponent(subject);
					mail += '&body=' + encodeURIComponent(list);
					document.querySelector('#maillink').href = mail;
				}
				else {
					document.querySelector('#maillink').href = 'mailto:';
				}
			}
		},

		//store temporary item in localStorage
		storeInput: function() {
			localStorage.setItem('inputvalue', this.value);
		},
		
		//scroll to top of list. called when user taps h1.
		scrollToTopList: function() {
		
			myScroll.scrollTo(0,0, 200);
		},
		
		getScrollerHeight: function() {
		
			wrapperHeight = window.innerHeight - (headerHeight + footerHeight),
            itemsOnScreen = wrapperHeight / listItemHeight;
		},

		//called once DOM has loaded
		loaded: function() {
	
			//check if the browser supports localStorage
			if (!supportsLocalStorage) {
				alert('Your device does not support HTML5 localStorage, sorry.');
			} 
			else {
				
				//if device has touch events use scrolling layer
				if (hasTouch) {
				
					document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
                
                	//if full screen, prevent document scrolling and show app header
                    if (isStandalone) {
                    
						document.querySelector('header').style.display = 'block';
						document.querySelector('#inputarea').style.top = '44px';
						document.querySelector('#edit').style.top = '44px';
						document.querySelector('#wrapper').style.top = '88px';
						
						//user can tap header to auto scroll to top of list
						document.querySelector('h1').addEventListener('touchstart', checklistApp.scrollToTopList, false);
                    }
                    
                    window.addEventListener('orientationchange', checklistApp.getScrollerHeight, false);
                    checklistApp.getScrollerHeight();
                    
                    //init scrolling layer
					myScroll = new iScroll('wrapper', { useTransition:true });
				}
				
				//init list
                checklistApp.getAllItems();
		
				//event listeners
				document.querySelector('#name').addEventListener('keyup', checklistApp.storeInput, false);
				document.querySelector('#deleteall').addEventListener('click', checklistApp.deleteAll, false);
				document.querySelector('#deletechecked').addEventListener('click', checklistApp.deleteChecked, false);
				document.querySelector('#deleteall').addEventListener('keydown', checklistApp.keyDeleteAll, false);
				document.querySelector('#deletechecked').addEventListener('keydown', checklistApp.keyDeleteChecked, false);
				
				document.querySelector('#inputarea').addEventListener('submit', function(e) {
    
					e.preventDefault();
                    
					checklistApp.addNewItem();
					
					if (itemAdded) {
						document.querySelector('#name').blur();
                        
                        if (hasTouch) {
                            setTimeout(function () { myScroll.refresh() }, 0);
                        }
					}
		
				}, true);
				
				document.querySelector('#add-button').addEventListener('click', function() {
					
					checklistApp.addNewItem();
					
					if (itemAdded) {
						document.querySelector('#name').blur();
                        
                        if (hasTouch) {
                            setTimeout(function () { myScroll.refresh() }, 0);
                        }
					}
					
					document.getElementById('add-button').blur();
						
				}, true);
			}
		}
	};
}());

window.addEventListener("DOMContentLoaded", checklistApp.loaded, true);

