// 
// All the product module specific code
//

var Product = {
	
	init:function()
	{

		// replace some text links with images
		$('#add-attribute a[rel="addAttribute"]').html('<img src="' + web_root + '/admin/images/add.png" alt="add" title="add" />');
		$('#add-attribute a[rel="showAdd"]').html('<img src="' + web_root + '/admin/images/delete.png" alt="cancel" title="cancel" />');
		$('#attributes a[rel="deleteAttribute"]').html('<img src="' + web_root + '/admin/images/bin.png" alt="delete" title="delete" />');
		
		$('#items a[rel="enable"]').html('<img src="' + web_root + '/admin/images/cross.png" alt="disabled" title="disabled" />');
		$('#items a[rel="disable"]').html('<img src="' + web_root + '/admin/images/tick.png" alt="enabled" title="enabled" />');

		// when clicking a button
		$('#attributes a').livequery('click', function()
		{
			// need to know which button they clicked
			var rel = $(this).attr('rel');

			if (rel == 'showAdd') {		
				// clear any values in the boxes
				$('#new_value').val('');
				$('#new_key').val('');
				$('#add-attribute').toggleClass('hidden');
				$('#primary .message').html('');	
			
			} else if (rel == 'addAttribute') {	
				// add the attribute				
				var row = $(this).parents('#attributes tr').get(0);
				
				Product.addAttribute(row);
			
			} else if (rel == 'deleteAttribute') {	
				// delete the attribute
				var row = $(this).parents('#attributes tr').get(0);
				
				Product.deleteAttribute(row);				
			}
			
			return false;	
		});
		
		// want to fire off updateAttribute when value changes
		// nb used livequery here as live does not support blur or focus yet
		var old_row;
		$('#attributes tbody tr td input').livequery('focus', function(){
			old_row = $(this).parents('#attributes tr').get(0);
			old_row = $(old_row).clone();
		});
		
		$('#attributes tbody tr td input').livequery('blur', function(){
			var new_row = $(this).parents('#attributes tr').get(0);
			
			var update = Product.updateAttribute(new_row,old_row);
			
			if(!update){
				$(this).val($('input',old_row).val())
			}
			
		});	
		
		// when enabling / disabling an item
		$('#items a').livequery('click', function()
		{
			// need to know what they clicked
			var rel = $(this).attr('rel');

			if (rel == 'enable') {		
				// set the hidden to 1, and change link
				$(this).attr('rel','disable');
				$(this).html('<img src="' + web_root + '/admin/images/tick.png" alt="enabled" title="enabled" />');
				$(this).next('input').val('1');
					
			} else if (rel == 'disable') {	
				// set the hidden to 0, and change link	 
				$(this).attr('rel','enable');				
				$(this).html('<img src="' + web_root + '/admin/images/cross.png" alt="disabled" title="disabled" />');
				$(this).next('input').val('0');
				
			}
						
			return false;	
		});

		// on update, check that everything is in order
		$('form').submit(function(){
			
			var valid = true;
			
			$('#primary .message').html('');
						
			// before we let it submit, check that any required blank fields all have a value in them
			$('#attributes tbody tr').each(function(){
				var row_key = Product.getKey(this);
				
				if(Product.isRequiredKey(this) && Product.isBlank(this)) {
					// is required and blank

					// get the nth-child
					var nth_child = Product.getNthChild(this);

					// iterate over the items table, and check that there is some value
					$('#items td:nth-child(' + nth_child + ')').each(function(){
						
						if(!$('input',this).val().length) {
							
							$('#primary .message').html('<p class="error">You must enter a value for each item for the required attribute ' + row_key + '</p>');							
							valid = false;	
						}
					})					
				}
			});				

			if (valid){
				alert('Success! This would now go and save the product, however as this is a demo nothing will happen.')
			}
			return false;
			
		});
			
	},
	
	// function for adding an attribute to this product
	addAttribute : function(row)
	{

		/* validation steps */
		
		// check there is a something in the key		
		if(!$('td:first-child input',row).val().length) {
			$('#primary .message').html('<p class="error">You must enter the name of the attribute</p>');
			return;
		}
		
		// if the key is not unique, then need to check for blankness of either new or existing value
		if(!Product.isUniqueKey(row) && (Product.isBlank(row) || Product.isPreExistingValueBlank(row))) {
			$('#primary .message').html('<p class="error">For a blank value, the name must be unique</p>');
			return;			
		}

		// check that it is a unique key value pair
		if (!Product.isUniqueKeyValuePair(row)) {
			$('#primary .message').html('<p class="error">Must be a unique name, value combination</p>');
			return;			
		}
		
		/* so it's passed all the validation stuff - now change the item table */
		
		if (Product.isBlank(row) && Product.isUniqueKey(row)) {
			// unique and blank - add a new col to the item table
			Product.addColumn(row);
		
		} else if (!Product.isUniqueKey(row)) {
			// non-unique, need to know how many exist
			if(Product.countKey(row) == 1 ) {
				// only one previously existed, need to add column and rows. 
				// nb. order of these functions is important!!
				Product.addColumn(row);
				Product.removeCommonAtt(row);
				Product.addRow(row);
			} else {
				// more than one previously existed, need to add rows
				Product.addRow(row);
			}
		} else if (Product.isUniqueKey(row) && !Product.isBlank(row)) {
			// is unique and non blank - add to Common attr's
			Product.addCommonAtt(row);
		}
		
		/* finally add it to the attributes table */

		var key = $('#new_key').val();
		var value = $('#new_value').val();
		
		// build the html
		var xhtml = '<tr';
		if (Product.isRequiredKey(row)) {
			xhtml += ' rel="required"';	
		}
		xhtml += '>';
		xhtml += '<td>' + key + '<input type="hidden" name="key[]" value="' + key + '" /></td>';
		xhtml += '<td><input name="value[]" value="' + value + '" /></td>';
		xhtml += '<td><a href="#" rel="deleteAttribute"><img src="' + web_root + '/admin/images/bin.png" alt="delete" title="delete" /></a></td>';
		xhtml += '</tr>';
		
		$('#attributes tbody').append(xhtml);
		
		// clear the add boxes
		$('#new_value').val('');
		$('#new_key').val('');
		$('#add-attribute').toggleClass('hidden');

		$('#primary .message').html('');
	
	},

	// function for updating an existing attribute on this product
	updateAttribute : function(new_row,old_row)
	{		
		
		var old_value = $('td:nth-child(2) input',old_row).val();
		var new_value = $('td:nth-child(2) input',new_row).val();
		
		// only want to do something if anything has changed
		if (new_value != old_value){

			/* validation steps */
			// if the key is not unique, then need to check for blankness of the new value
			if(!Product.isUniqueKey(new_row) && Product.isBlank(new_row)) {
				$('#primary .message').html('<p class="error">For a blank value, the name must be unique</p>');
				return false;			
			}
	
			// check that it is a unique key value pair
			if (!Product.isUniqueKeyValuePair(new_row)) {
				$('#primary .message').html('<p class="error">Must be a unique name, value combination</p>');
				return false;			
			}
			
			/* so it's passed all the validation stuff - now change the item table */
			
			if (Product.isBlank(old_row) && !Product.isBlank(new_row)) {
				// was previously blank now a value, so remove column, and add to commom atts 
				// (as it was blank, we know that it is unique)
				Product.deleteColumn(old_row);
				Product.addCommonAtt(new_row);
			
			} else if (Product.isBlank(new_row) && !Product.isBlank(old_row)) {
				// was a value, is now blank, so remove common att, and add new column
				// (we know from validation above it is unique)
				// nb. order of these functions is important!!
				Product.addColumn(new_row);
				Product.removeCommonAtt(old_row);
				
			} else {
				// is a value to a diff value
				if(Product.isUniqueKey(new_row)) {
					// is unique key : update common att (nb we know the key stays the same)
					Product.updateCommonAtt(new_row);
				} else {
					// is non unique : replace old text with new
					Product.updateRows(new_row,old_row);
				}
			}
			
		}
		
		$('#primary .message').html('');
		
		return true;

	},

	// function for deleting an attribute from this product
	deleteAttribute : function(row)
	{	
		
		/* all the validation steps */
		
		// check if is the last instance of this required key
		if(Product.isRequiredKey(row) && Product.countKey(row) == 1) {
			$('#primary .message').html('<p class="error">You cannot remove this required attribute from the product</p>');
			return;			 
		}
		
		/* so it's passed all the validation stuff - now change the item table */
		
		if(Product.isBlank(row)) {
			// row is blank - remove column
			Product.deleteColumn(row);
			
		} else if(Product.isUniqueKey(row)) {
			// row is unique (but not blank) - remove from common atts
			Product.removeCommonAtt(row);
			
		} else {
			// non unique row - always remove the rows with this value
			Product.deleteRow(row);
			
			if(Product.countKey(row) == 2) {
				// currently two, therefore will only be one after deletion,
				// so remove column, and add to common atts
				Product.deleteColumn(row);
				
				// need to find the values from before
				
				var row_key = Product.getKey(row);
				var row_value = $('td:nth-child(2) input',row).val();
				var other_row = '';
				
				// iterate over the attributes table, and pluck the row that isn't this one, but has same key
				$('#attributes tbody tr').each(function(){
					var key = $('td:first-child',this).text();
					var value = $('td:nth-child(2) input',this).val();
					
					if(key == row_key && value != row_value){
						other_row = $(this).clone();
					}
							
				});					
				Product.addCommonAtt(other_row);
			}
			
		}
		
		/* finally, remove the row from the attributes table */
		
		$(row).remove();
		$('#primary .message').html('');
	
	},

	/*
	 * Functions to change the items table
	 */
	
	// addColumn - adds a new column to the item table
	addColumn : function(row)
	{
		
		var row_key = Product.getKey(row);

		// now add the column

		// the header
		$('#items th.common_atts').before('<th>' + row_key + '</th>');	

		// now iterate over all rows adding the td's
		$('#items tbody td.common_atts').each(function(){
			$(this).before('<td></td>');		
		});	

		// get the nth-child
		var nth_child = Product.getNthChild(row);

		// first need to find out what needs to be put in the column

		if (Product.isBlank(row)) {
			
			// if blank 
			$('#items tbody td:nth-child(' + nth_child + ')').html('<input type="text" name="item_' + row_key + '[]" value="" />');
			
		} else {
			
			var value = '';
			// iterate over the dt's and pick the value of this key
			$('#items tbody tr:first-child td.common_atts dl dt').each(function(){
				if ($(this).text() == row_key) {
					value = $(this).next('dd').text();
				}
			});
			
			$('#items tbody td:nth-child(' + nth_child + ')').html(Product.getInputHiddenHtml(row_key,value));

		}
		
	},

	// deleteColumne - remove column
	deleteColumn : function(row)
	{

		// get the nth-child
		var nth_child = Product.getNthChild(row);
		
		// delete the th/td nth-children from the table
		$('#items td:nth-child(' + nth_child + ')').remove();
		$('#items th:nth-child(' + nth_child + ')').remove();
		
	},
	
	// addRow - adds new row(s) to the item table
	addRow : function(row)
	{
		
		var row_key = Product.getKey(row); 
		var row_value = $('td:nth-child(2) input',row).val();

		// get the nth-child value of the already existing column
		var nth_child = Product.getNthChild(row);
		
		// clone all rows of a diff value for this key, as this will already be a column in the table
		
		// use a cell from the first row as the item we're going to clone
		var clone_cell = $('#items tbody tr:first-child td:nth-child(' + nth_child + ')').text();
		
		// iterate over the rows, cloning it where the cell is the same as the clone_cell
		$('#items tbody tr').each(function(){
		
			var cell = $('td:nth-child(' + nth_child + ')',this).text();
			
			if(clone_cell == cell) {
				
				// is the same, so clone
				var row = $(this).clone();
				
				// clear any text inputs
				$('td input[type="text"]',row).val('');
				// set all the new ones to enabled				
				$('td:last-child a',row).attr('rel','disable');
				$('td:last-child a',row).html('<img src="' + web_root + '/admin/images/tick.png" alt="enabled" title="enabled" />');
				$('td:last-child input[type="hidden"]',row).val('1');
				
				// update the value of the nth-child to the new stuff
				$('td:nth-child(' + nth_child + ')',row).html(Product.getInputHiddenHtml(row_key,row_value));
				
				// now add the row to the table
				$('#items tbody').append(row);
				
			}
		
		});			
		
	},

	// deleteRow - deletes given row
	deleteRow : function(row)
	{

		var row_value = $('td:nth-child(2) input',row).val();

		// get the nth-child value of the already existing column
		var nth_child = Product.getNthChild(row);
		
		var to_remove;
		
		// iterate over the rows of the items table, removing 
		$('#items tbody tr').each(function(){
			var value = $('td:nth-child(' + nth_child + ')',this).text();
			value = $.trim(value);
			
			if (value == row_value){
				$(this).remove();
			}
			
		});
		
	},
	
	// updateRows - updates to the new value when it's changed
	updateRows : function(new_row,old_row)
	{
		
		var row_key = Product.getKey(new_row); 
		var new_value = $('td:nth-child(2) input',new_row).val();
		var old_value = $('td:nth-child(2) input',old_row).val();
		
		// get the nth-child value of the already existing column
		var nth_child = Product.getNthChild(new_row);
		
		// overwrite the nth-child with new stuff
		$('#items tbody tr td:nth-child(' + nth_child + ')').each(function(){
			var value = $('input',this).val();
			
			if (value == old_value){
				$(this).html(Product.getInputHiddenHtml(row_key,new_value));
			}
			
		});
		
	},

	// addCommonAtt - adds a new common attribute to the item table
	addCommonAtt : function(row)
	{

		var row_key = Product.getKey(row);
		var row_value = $('td:nth-child(2) input',row).val(); 
		
		var xhtml = '<dt>' + row_key + '</dt><dd>' + row_value + '</dd>';
		
		// iterate over the row's and add the xhtml
		$('#items tbody tr td.common_atts').each(function(){
			$('dl',this).append(xhtml);
		});	
				
	},

	// updateCommonAtt - updates a pre-existing common attribute in the item table
	updateCommonAtt : function(row)
	{
	
		var row_key = Product.getKey(row);
		var row_value = $('td:nth-child(2) input',row).val(); 
		
		// iterate over the dt's and override the value of this key
		$('#items tbody tr td.common_atts dl dt').each(function(){
			
			if ($(this).text() == row_key) {
				$(this).next('dd').text(row_value);
			}
			
		});			
		
	},

	// removeCommonAtt - removes a common attribute from the item table
	removeCommonAtt : function(row)
	{
		
		var row_key = Product.getKey(row);	
		
		// iterate over the dt's and pick the value of this key
		$('#items tbody tr td.common_atts dl dt').each(function(){
			
			var text = $(this).text();
			text = $.trim(text);
			
			if (text == row_key) {
				$(this).next('dd').remove();
				$(this).remove();
			}
			
		});		
		
	},
				
	/*
	 * All the utility functions to be utilised above
	 */
	
	// isUniqueKey - checks whether the key in this row is unique or not
	isUniqueKey : function(row)
	{
		
		var unique = true;
		var row_key = Product.getKey(row); 
		
		// iterate over the all the rows
		$('#attributes tbody tr').each(function(){
			
			var key = $('td:first-child',this).text();
			
			// check if key already exists (but don't check against itself!)
			if (row != this && key == row_key) {
				unique = false;
			}
		
		});
		
		return unique;	
	},

	// isBlank - checks whether the value in this row is blank or not
	isBlank : function(row)
	{	
		if($('td:nth-child(2) input',row).val()) {
			return false;
		} else {
			return true;
		}
	},

	// isPreExistingValueBlank - checks whether the previous value for the key in this row is blank or not
	isPreExistingValueBlank : function(row)
	{	
		
		var blank = false;
		var row_key = Product.getKey(row); 

		// iterate over the all the rows
		$('#attributes tbody tr').each(function(){

			var key = $('td:first-child',this).text();
			var value = $('td:nth-child(2) input',this).val();
			
			// check if key already exists with a blank value (but don't check against itself!)
			if (key == row_key && this != row && !value) {
				blank = true;
			}
		});
				
		return blank;
	},
	
	// countKey - counts the number of times the key from this row is used in
	// the atts that are there at the moment (incl. itself if editing/deleting)
	countKey : function(row)
	{
		
		var row_key = Product.getKey(row); 
		var count = 0;

		// iterate over the all the rows
		$('#attributes tbody tr').each(function(){

			var key = $('td:first-child',this).text();

			// check if key alreay exists (but don't check against itself!)
			if (key == row_key) {
				count += 1;
			}
		});
		
		return count;
		
	},

	// isUniqueKeyValuePair - checks whether the key value pair in this row is unique or not
	isUniqueKeyValuePair : function(row)
	{

		var unique = true;
		var row_key = Product.getKey(row); 
		
		// get the value
		var row_value = $('td:nth-child(2) input',row).val();
		
		// iterate over the all the rows
		$('#attributes tbody tr').each(function(){
			
			var key = $('td:first-child',this).text();
			var value = $('td:nth-child(2) input',this).val();
			
			// check if key-value pair alreay exists (but don't check against itself!)
			if (row != this && key == row_key && value == row_value) {
				unique = false;
			}
		
		});
		
		return unique;		
		
	},
	
	// isRequired - checks whether this key is required or not
	isRequiredKey : function(row)
	{
		
		var required = false;
		var row_key = Product.getKey(row); 
		
		// now iterate, over the existing rows, to see if any with this key are required
		// - on delete this will pick up itself (and poss others), and on add will pick up others
		$('#attributes tbody tr').each(function(){

			var key = $('td:first-child',this).text();
			var rel = $(this).attr('rel');
			
			// check if key is same and required
			if (key == row_key && rel == 'required') {
				required = true;
			}
		
		});
		
		return required;		
		
	},
	
	// getKey - returns the key, given a row
	getKey : function(row)
	{

		// get the row key - if the input is there (ie adding) use the val, 
		// otherwise use the text (ie edit / deleting)
		if($('td:first-child input',row).length) {
			var row_key = $('td:first-child input',row).val();
		} else {
			var row_key = $('td:first-child',row).text();
		}
		
		return row_key;
		
	},
	
	// getNthChild - returns the td/th nth-child for the value from this key 
	getNthChild : function(row)
	{

		var row_key = Product.getKey(row); 
		var nth_child = 1;
		
		$('#items thead tr th').each(function(){
			var text = $(this).text();
			
			if (text == row_key){
				return false;
			}
			
			nth_child += 1;
			
		});
		
		return nth_child;
	},
	
	// getInputHiddenHtml - returns the html markup required for the text cells
	getInputHiddenHtml : function(key,value)
	{
		var xhtml = value + '<input type="hidden" name="item_' + key + '[]" value="' + value + '" />';
		return xhtml;
	}
	
}
$(document).ready(Product.init);
