function palleteHelper(baseUrl, lang, controller, seperator) {
	
	this.baseUrl = baseUrl;
	this.lang = lang;
	this.controller = controller;
	
	this.seperator = seperator;
	
	this.defaultSection = 'pall';
	
	this.index = 0;
	this.css = ''; 
	
	/* this.mozillaLastPallete = []; */
}

palleteHelper.prototype.init = function() {
	
	var self = this;
	
	self.initLayout();
	self.initEvents();
	self.initColorPicker();
	
	self.dispatch();
}

palleteHelper.prototype.initLayout = function() {
	
	this.container = $('#layout-block');
	this.form = $('#template-palletes-form');
	this.menuContainer = $('#pallete-sections');
	
	this.colorStripes = $('div.lovers-thumb-big div.thumb span.c');
	this.colorIcons = $('ul.lovers-thumb-lit li');
	
	this.favoriteButton = $('#pfavorite-button');
	this.applyButton = $('#papply-button');
	
	this.listContainer = $('#pallete-list');
	this.pagesContainer = $('#pallete-page-container');
}

palleteHelper.prototype.initEvents = function() {

	var self = this;
	
	self.form.submit(function(event) {
		event.preventDefault();
	}); 
	
	self.menuContainer.find('li').click(function() {
		
		var section = $(this).attr('id').split('-');
		section = section[section.length-1];
		
		window.location.hash = '#' + section;
		self.dispatch(section);
	});
	
	self.colorIcons.each(function(index) {
		
		$(this).click(function() {
			
			var color = $(this).css('backgroundColor');
			var opacity = opacity_from_rgba(color);
			
			// Mozilla Firefox "transparent" fix
			/*
			if (color == 'transparent' && self.mozillaLastPallete.hasOwnProperty(index)) {
				
				opacity = 0;
				color = self.mozillaLastPallete[index];
			}
			*/
			
			self.index = index;
			self.colorPicker.setColor(color);
			
			self.colorPicker.setOpacity(opacity);
			self.colorPicker.show();
		})
	});
	
	self.applyButton.click(function() {
		
		self.applyAction(function() {
			self.applyButton.addClass('hidden');
		});
	}) 
	
	self.favoriteButton.click(function() {
		self.likeAction();
	}) 
	
	self.getItems().live('click', function() {
		self.item2Pallete($(this));
	}) 
	
	self.getItems().find('div.thumb div.delete').live('click', function(event) {
		
		var hash = $(this).parent().parent().find('span.hidden').html();
		
		var callback = function() {
			
			alertPopup.hideBox();
			
			self.unlikeAction(hash,  function() {
				alertPopup.hideBackground();
			});
		}	

		var alertPopup = new alertPopupHelper('alert', 'txt_pallete_unlike_warning', 'button_confirm', 'button_cancel', callback);	
		alertPopup.show();
		
		return false;
	})
	
	self.getItems().live('mouseover', function() {
		$(this).find('div.delete').show();
	})
	
	self.getItems().live('mouseout', function() {
		$(this).find('div.delete').hide();
	})
	
	self.pagesContainer.find('ul.lovers-nav li.prev-arrow').click(function() {
		self.pagePreviousAction();
	})
	
	self.pagesContainer.find('ul.lovers-nav li.next-arrow').click(function() {
		self.pageNextAction();
	})
	
	if (backgroundPanel.bgHelper) {
		
		var parentMethod = backgroundPanel.bgHelper.afterApplyBackground;
		
		backgroundPanel.bgHelper.afterApplyBackground = function() {
			
			parentMethod();
			
			var colors = this.getList().items[this.lastAppliedItem].colors;
			colors = colors.split(',');
			
			var pallete = [];
			
			if (this.section == 'patternsRandom') {
			
				pallete.push('rgb(255,255,255)');
				pallete.push('rgb(0,0,0)');
			}
			
			for (key in colors) {
				
				var color = hex_to_rgba_css(colors[key]);
				pallete.push(color);
			}
			
			self.previewPallete('pallete', pallete, true);
		}
	}
}

palleteHelper.prototype.initColorPicker = function() { 

	var self = this;
	
	self.colorPicker = new colorPickerHelper('pallete-cp-');
	self.colorPicker.init(); 
	
	self.colorPicker.colorCallBack = function(color) {
		
		self.previewPallete('color', color);
		self.saveMozillaLastPallete();
	};
	
	self.colorPicker.opacityCallBack = function(opacity) {
		
		self.previewPallete('opacity', opacity);
		self.saveMozillaLastPallete();
	};
}

palleteHelper.prototype.getUrl = function() {
	return this.baseUrl + '/' + this.lang + '/' + this.controller;
}

palleteHelper.prototype.flagBusy = function() {
	
	self.busy = true;
	$('#' + whiteLayerId).removeClass('hidden');
}

palleteHelper.prototype.flagReady = function() {

	$('#' + whiteLayerId).addClass('hidden');
	self.busy = false;
}

palleteHelper.prototype.dispatch = function(section) { 
	
	if (!section) {
		
		section = window.location.hash.replace('#', '');
		section = section ? section : this.defaultSection;
	}
	
	this.section = section;
	this.currentPage = 1;
	this.pageCount = 0;
	this.busy = false;
	
	this.highlightSection();
	this.palleteAction();
}

palleteHelper.prototype.highlightSection = function() {
	
	var itemId = this.menuContainer.attr('id') + '-' + this.section;
	var item = $('#' + itemId);
	
	this.menuContainer.find('li').removeClass('active');
	item.addClass('active');
}

palleteHelper.prototype.previewPallete = function(type, value, silent) {
	
	if (!silent) {
		this.applyButton.removeClass('hidden');
	}	
	
	switch (type) {
	
		case 'color':
			
			var color = this.getIconColor(this.index);
			
			// Mozilla Firefox "transparent" fix
			
			/*
			if (color == 'transparent' && this.mozillaLastPallete.hasOwnProperty(this.index)) {
				var opacity = 0;
			}
			else {
			*/
				var opacity = opacity_from_rgba(color);
			/*	
			}
			*/
			
			/*
			pp(value);
			pp(color);
			*/
			
			value = value.indexOf('rgba') < 0 ? rgb_to_rgba(value, opacity) : opacity_to_rgba(value, opacity);
			this.previewPalleteColor(this.index, value, silent);
			
		break;
		
		case 'opacity':
			
			var color = this.getIconColor(this.index);
			color = color.indexOf('rgba') < 0 ? rgb_to_rgba(color, value) : opacity_to_rgba(color, value);
			
			this.previewPalleteColor(this.index, color, silent);
			
		break;
		
		case 'pallete':
		
			for (index in value) {
				this.previewPalleteColor(index, value[index]);
			}
			
			this.applyAction();
			
		break;
		
		case 'preview-pallete':
		
			for (index in value) {
				
				/* this.mozillaLastPallete[index] = value[index]; */
				this.previewPalleteColor(index, value[index]);
			}
			
		break;
	}
}

palleteHelper.prototype.getStripeColor = function(index) {
	return $(this.colorStripes.get(index)).css('backgroundColor');
}

palleteHelper.prototype.getIconColor = function(index) {
	return $(this.colorIcons.get(index)).css('backgroundColor');
}

palleteHelper.prototype.setStripeColor = function(index, value) {
	$(this.colorStripes.get(index)).css({'backgroundColor': value});
}

palleteHelper.prototype.setIconColor = function(index, value) {
	$(this.colorIcons.get(index)).css({'backgroundColor': value});
}

palleteHelper.prototype.previewPalleteColor = function(index, color, silent) {
	
	// preview pallete color
	
	this.setStripeColor(index, color);
	this.setIconColor(index, color);
	
	if (!silent) {
		
		// preview template color
		
		var pattern = '\\/\\*<INDEX>\\*\\/(.*)\\/\\*<\\/INDEX>\\*\\/';
		pattern = pattern.replace(/INDEX/g, index);
	
		var regExp = new RegExp(pattern);
		var cssSample = this.css.match(regExp);
		
		if (!cssSample) {
			return;
		}
		
		var oldColor = cssSample[1].match(/(rgba?\([0-9,. ]{1,}\))/);
		
		if (!oldColor) {
			return;
		}
		
		regExp = new RegExp(preg_quote(oldColor[1]), '\g');
		newCssSample = cssSample[1].replace(regExp, color);
		
		this.css = this.css.replace(cssSample[1], newCssSample);
		
		$('head style').remove();
		$('head').append('<style type="text/css">' + this.css + '</style>');
	}	
}

palleteHelper.prototype.getPallete_OLD = function() {
	
	var pallete = [];
	
	this.colorIcons.each(function() { 
		
		var backgroundColor = $(this).css('backgroundColor');
		pallete.push(backgroundColor);
	})
	
	return pallete;
}

palleteHelper.prototype.getPallete = function() { 
	
	var self = this;
	
	var pallete = [];
	var opacity = 0;
	
	this.colorIcons.each(function(index) { 
		
		var backgroundColor = $(this).css('backgroundColor');
		
		// Mozilla Firefox "transparent" fix
		/*
		if (backgroundColor == 'transparent' && self.mozillaLastPallete.hasOwnProperty(index)) {
			backgroundColor = opacity_to_rgba(self.mozillaLastPallete[index], opacity);
		}
		*/
		
		pallete.push(backgroundColor);
	})
	
	return pallete;
}

palleteHelper.prototype.saveMozillaLastPallete = function() {
	
	/* remove later */
	return;
	
	var pallete = this.getPallete();
	
	for (index in pallete) {
		
		if (!pallete.hasOwnProperty(index)) {
			continue;
		}
		/*
		if (pallete[index].indexOf('transparent') == -1) {
			this.mozillaLastPallete[index] = pallete[index];
		}
		*/
	}
}

palleteHelper.prototype.getItemPallete = function(Object) {
	
	var pallete = [];
	
	Object.find('span.c').each(function() { 
		
		var backgroundColor = $(this).css('backgroundColor');
		pallete.push(backgroundColor);
	})
	
	return pallete;
}

palleteHelper.prototype.palleteAction = function(callback) {

	var self = this;	
	
	$.ajax({
		
		type: 'POST',
		url: self.getUrl(),
		data: '_action=ajaxPallete',
		dataType: 'json',
		
		success: function(Object) {
		
			if (Object.pallete) {
				self.previewPallete('preview-pallete', Object.pallete, true);
			}
		
			if (Object.css) {
				self.css = Object.css;
			}
			
			self.indexAction();
			
			if (callback) {
				callback();
			}
		}	
	})
}

palleteHelper.prototype.indexAction = function(callback) {

	var self = this;	

	$.ajax({
		
		type: 'POST',
		url: self.getUrl(),
		data: '_action=ajaxIndex',
		dataType: 'json',
		
		success: function(Object) {
		
			self.pageCount = Object.pageCount;
		
			self.listAction(self.currentPage, function() {
				self.container.fadeIn(500);
			});
		
			if (callback) {
				callback();
			}
		}	
	})
}

palleteHelper.prototype.listAction = function(page, callback) {

	var self = this;
	
	if (!self.busy) {
		
		//self.flagBusy();
		self.currentPage = page ? page : 1;
		
		$.ajax({
			
			type: 'POST',
			url: self.getUrl(),
			data: '_action=ajaxList&page=' + self.currentPage,
			dataType: 'json',
			
			error: function(xhr, ajaxOptions, thrownError){
				//self.flagReady();
	        },  
			
			success: function(Object) {
			
				if (!Object) {
					return ;
				}
				
				self.appendItems(Object);
				self.updatePageStatus();
				
				if (callback) {
					callback();
				}
				
				//self.flagReady();
			}	
		})
	}	
}

palleteHelper.prototype.getItems = function() {
	return this.listContainer.find('li');
}

palleteHelper.prototype.appendItems = function(Object) {
	
	var itemCount = assosiativeCount(Object.items);
	
	this.getItems().remove();
	
	if (!Object.items || !itemCount) {
		return ;
	}
	
	var itemKeys = array_keys(Object.items);
	itemKeys.sort(function(a, b) {return b - a});
	
	for (key in itemKeys) { 
		
		if (!itemKeys.hasOwnProperty(key)) {
			continue ;
		}
	
		var item = Object.items[itemKeys[key]];
		this.appendItem(item);
	}	
}

palleteHelper.prototype.appendItem = function(item) { 

	var deleteButton = item.owner ? '<div class="delete" style="display: none"><span>delete</span></div>' : '';
	
	var pallete = '';
	
	for (var i=0; i<item.pallete.length; i++) {
		pallete += '<span class="c" style="background-color: ' + item.pallete[i] + '"><!-- color --></span>'
	}
	
	var html =
		'<li>' + 
			'<span class="hidden">' + item.hash + '</span>' +
			'<div class="thumb">' +
				deleteButton + 
				pallete +
			'</div>';	
		'</li>';
	
	this.listContainer.append(html); 
}

palleteHelper.prototype.updatePageStatus = function() {
	
	if (this.pageCount > 1) {
		
		this.pagesContainer.show();
		
		if (this.currentPage == 1) {
			
			this.pagesContainer.find('ul.lovers-nav li.prev-arrow').hide();
			this.pagesContainer.find('ul.lovers-nav li.next-arrow').show();
		}
		else if (this.currentPage == this.pageCount) { 
			
			this.pagesContainer.find('ul.lovers-nav li.next-arrow').hide();
			this.pagesContainer.find('ul.lovers-nav li.prev-arrow').show();
		}
		else {
			
			this.pagesContainer.find('ul.lovers-nav li.prev-arrow').show();
			this.pagesContainer.find('ul.lovers-nav li.next-arrow').show();
		}
		
		var pageCountHTML = this.currentPage + '/' + this.pageCount;
		this.pagesContainer.find('ul.lovers-nav li.count-adm').html(pageCountHTML);
	}
	else {
		this.pagesContainer.hide();
	}
}

palleteHelper.prototype.likeAction = function() {
	
	var self = this;
	
	if (!self.busy) {
		
		self.flagBusy();
		
		var pallete = self.getPallete().join(self.seperator);
		
		$.ajax({
			
			type: 'POST',
			url: self.getUrl(),
			data: '_action=ajaxLike&pallete=' + pallete,
			
			error: function(xhr, ajaxOptions, thrownError){
				self.flagReady();
	        },  
			
			success: function() {
	
	        	self.currentPage = 1;
	        	
	        	self.indexAction(function() {
	        		self.flagReady();
	        	});
			}	
		})
	}	
}

palleteHelper.prototype.unlikeAction = function(hash, callback) {
	
	var self = this;
	
	$.ajax({
		
		type: 'POST',
		url: self.getUrl(),
		data: '_action=ajaxUnlike&hash=' + hash,
		
		error: function(xhr, ajaxOptions, thrownError){
			self.indexAction(callback);
        },  
		
		success: function() {
        	
        	self.currentPage = 1;
        	self.indexAction(callback);
		}	
	})
}

palleteHelper.prototype.pageAction = function(page) {
	this.listAction(page);
}

palleteHelper.prototype.pagePreviousAction = function() { 
	
	if (this.currentPage > 1) {
		this.currentPage--;
	}
	
	this.pageAction(this.currentPage);
}

palleteHelper.prototype.pageNextAction = function() { 
	
	if (this.currentPage < this.pageCount) {
		this.currentPage++;
	}
	
	this.pageAction(this.currentPage);
}

palleteHelper.prototype.item2Pallete = function(Object) {

	var pallete = this.getItemPallete(Object); 
	
	this.previewPallete('pallete', pallete, true);
}

palleteHelper.prototype.applyAction = function(callback) {
	
	var self = this;
	
	if (!self.busy) {
		
		self.flagBusy();
		
		var pallete = self.getPallete().join(self.seperator);
		
		$.ajax({
			
			type: 'POST',
			url: self.getUrl(),
			data: '_action=ajaxApply&pallete=' + pallete,
			
			error: function(xhr, ajaxOptions, thrownError){
				self.flagReady();
	        },  
			
			success: function() {
	        	
	        	if (callback) {
	        		callback();
	        	}
	        	
	        	self.flagReady();
			}	
		})
	}	
}
