Page.Settings = new Class({

	Extends: PageBase,

	order: 50,
	name: 'settings',
	title: 'Change settings.',
	wizard_only: false,

	tabs: {},
	lists: {},
	current: 'about',
	has_tab: false,

	open: function(action, params){
		var self = this;
		self.action = action == 'index' ? self.default_action : action;
		self.params = params;

		if(!self.data)
			self.getData(self.create.bind(self));
		else {
			self.openTab(action);
		}

		App.getBlock('navigation').activate(self.name);
	},

	openTab: function(action){
		var self = this,
			action = (action == 'index' ? 'about' : action) || self.action;

		if(self.current)
			self.toggleTab(self.current, true);

		var tab = self.toggleTab(action);
		self.current = tab == self.tabs.general ? 'general' : action;

	},

	toggleTab: function(tab_name, hide){
		var self = this;

		var a = hide ? 'removeClass' : 'addClass';
		var c = 'active';

		var t = self.tabs[tab_name] || self.tabs[self.action] || self.tabs.general;

		// Subtab
		var subtab = null;
		Object.each(self.params, function(param, subtab_name){
			subtab = subtab_name;
		});

		self.el.getElements('li.'+c+' , .tab_content.'+c).each(function(active){
			active.removeClass(c);
		});

		if(t.subtabs[subtab]){
			t.tab[a](c);
			t.subtabs[subtab].tab[a](c);
			t.subtabs[subtab].content[a](c);

			if(!hide)
				t.subtabs[subtab].content.fireEvent('activate');
		}
		else {
			t.tab[a](c);
			t.content[a](c);

			if(!hide)
				t.content.fireEvent('activate');
		}

		return t
	},

	getData: function(onComplete){
		var self = this;

		if(onComplete)
			Api.request('settings', {
				'useSpinner': true,
				'spinnerOptions': {
					'target': self.el
				},
				'onComplete': function(json){
					self.data = json;
					onComplete(json);
				}
			});

		return self.data;
	},

	getValue: function(section, name){
		var self = this;
		try {
			return self.data.values[section][name];
		}
		catch(e){
			return ''
		}
	},

	showAdvanced: function(){
		var self = this;

		var c = self.advanced_toggle.checked ? 'addClass' : 'removeClass';
		self.el[c]('show_advanced');

		Cookie.write('advanced_toggle_checked', +self.advanced_toggle.checked, {'duration': 365});
	},

    sortByOrder: function(a, b){
		return (a.order || 100) - (b.order || 100)
	},

	create: function(json){
		var self = this;

		self.tabs_container = new Element('ul.tabs');
		self.containers = new Element('form.uniForm.containers', {
			'events': {
				'click:relay(.enabler.disabled h2)': function(e, el){
					el.getPrevious().getElements('.check').fireEvent('click');
				}
			}
		}).adopt(
			new Element('label.advanced_toggle').adopt(
				new Element('span', {
					'text': 'Show advanced settings'
				}),
				self.advanced_toggle = new Element('input[type=checkbox].inlay', {
					'checked': +Cookie.read('advanced_toggle_checked'),
					'events': {
						'change': self.showAdvanced.bind(self)
					}
				})
			)
		);
		self.showAdvanced();

		new Form.Check(self.advanced_toggle);

		// Add content to tabs
		var options = [];
		Object.each(json.options, function(section, section_name){
			section['section_name'] = section_name;
			options.include(section);
		});

		options.stableSort(self.sortByOrder).each(function(section){
			var section_name = section.section_name;

			// Add groups to content
			section.groups.stableSort(self.sortByOrder).each(function(group){
				if(group.hidden) return;

				if(self.wizard_only && !group.wizard)
					return;

				// Create tab
				if(!self.tabs[group.tab] || !self.tabs[group.tab].groups)
					self.createTab(group.tab, {});
				var content_container = self.tabs[group.tab].content;

				// Create subtab
				if(group.subtab){
					if(!self.tabs[group.tab].subtabs[group.subtab])
						self.createSubTab(group.subtab, group, self.tabs[group.tab], group.tab);
					content_container = self.tabs[group.tab].subtabs[group.subtab].content
				}

				if(group.list && !self.lists[group.list]){
					self.lists[group.list] = self.createList(content_container);
				}

				// Create the group
				if(!self.tabs[group.tab].groups[group.name])
					self.tabs[group.tab].groups[group.name] = self.createGroup(group)
						.inject(group.list ? self.lists[group.list] : content_container)
						.addClass('section_'+section_name);

				// Create list if needed
				if(group.type && group.type == 'list'){
					if(!self.lists[group.name])
						self.lists[group.name] = self.createList(content_container);
					else
						self.lists[group.name].inject(self.tabs[group.tab].groups[group.name]);
				}

				// Add options to group
				group.options.stableSort(self.sortByOrder).each(function(option){
					if(option.hidden) return;
					var class_name = (option.type || 'string').capitalize();
					var input = new Option[class_name](section_name, option.name, self.getValue(section_name, option.name), option);
						input.inject(self.tabs[group.tab].groups[group.name]);
						input.fireEvent('injected');
				});

			});
		});

		setTimeout(function(){
			self.el.adopt(
				self.tabs_container,
				self.containers
			);

			self.fireEvent('create');
			self.openTab();
		}, 0);

	},

	createTab: function(tab_name, tab){
		var self = this;

		if(self.tabs[tab_name] && self.tabs[tab_name].tab)
			return self.tabs[tab_name].tab;

		var label = tab.label || (tab.name || tab_name).capitalize();
		var tab_el = new Element('li.t_'+tab_name).adopt(
			new Element('a', {
				'href': App.createUrl(self.name+'/'+tab_name),
				'text': label
			}).adopt()
		).inject(self.tabs_container);

		if(!self.tabs[tab_name])
			self.tabs[tab_name] = {
				'label': label
			};

		self.tabs[tab_name] = Object.merge(self.tabs[tab_name], {
			'tab': tab_el,
			'subtabs': {},
			'content': new Element('div.tab_content.tab_' + tab_name).inject(self.containers),
			'groups': {}
		});

		return self.tabs[tab_name]

	},

	createSubTab: function(tab_name, tab, parent_tab, parent_tab_name){
		var self = this;

		if(parent_tab.subtabs[tab_name])
			return parent_tab.subtabs[tab_name];

		if(!parent_tab.subtabs_el)
			parent_tab.subtabs_el = new Element('ul.subtabs').inject(parent_tab.tab);

		var label = tab.subtab_label || tab_name.replace('_', ' ').capitalize();
		var tab_el = new Element('li.t_'+tab_name).adopt(
			new Element('a', {
				'href': App.createUrl(self.name+'/'+parent_tab_name+'/'+tab_name),
				'text': label
			}).adopt()
		).inject(parent_tab.subtabs_el);

		if(!parent_tab.subtabs[tab_name])
			parent_tab.subtabs[tab_name] = {
				'label': label
			};

		parent_tab.subtabs[tab_name] = Object.merge(parent_tab.subtabs[tab_name], {
			'tab': tab_el,
			'content': new Element('div.tab_content.tab_'+tab_name).inject(self.containers),
			'groups': {}
		});

		return parent_tab.subtabs[tab_name]

	},

	createGroup: function(group){

		if((typeOf(group.description) == 'array')){
			var hint = new Element('span.hint.more_hint', {
				'html': group.description[0]
			});

			createTooltip(group.description[1]).inject(hint, 'top');
		}
		else {
			var hint = new Element('span.hint', {
				'html': group.description || ''
			})
		}

		var icon;
		if(group.icon){
			icon = new Element('span.icon').grab(new Element('img', {
				'src': 'data:image/png;base64,' + group.icon
			}));
		}

		var label = new Element('span.group_label', {
			'text': group.label || (group.name).capitalize()
		})

		return new Element('fieldset', {
			'class': (group.advanced ? 'inlineLabels advanced' : 'inlineLabels') + ' group_' + (group.name || '') + ' subtab_' + (group.subtab || '')
		}).grab(
			new Element('h2').adopt(icon, label, hint)
		);

	},

	createList: function(content_container){
		return new Element('div.option_list').grab(
			new Element('h3', {
				'text': 'Enable another'
			})
		).inject(content_container)
	}

});

var OptionBase = new Class({

	Implements: [Options, Events],

	klass: 'textInput',
	focused_class: 'focused',
	save_on_change: true,

	initialize: function(section, name, value, options){
		var self = this;
		self.setOptions(options);

		self.section = section;
		self.name = name;
		self.value = self.previous_value = value;

		self.createBase();
		self.create();
		self.createHint();
		self.setAdvanced();

		// Add focus events
		self.input.addEvents({
			'change': self.changed.bind(self),
			'keyup': self.changed.bind(self)
		});

		self.addEvent('injected', self.afterInject.bind(self))

	},

	/**
	 * Create the element
	 */
	createBase: function(){
		var self = this;
		self.el = new Element('div.ctrlHolder.' + self.section + '_' + self.name)
	},

	create: function(){
	},

	createLabel: function(){
		var self = this;
		return new Element('label', {
			'text': (self.options.label || self.options.name.replace('_', ' ')).capitalize()
		})
	},

	setAdvanced: function(){
		this.el.addClass(this.options.advanced ? 'advanced' : '')
	},

	createHint: function(){
		var self = this;
		if(self.options.description){


			if((typeOf(self.options.description) == 'array')){
				var hint = new Element('p.formHint.more_hint', {
					'html': self.options.description[0]
				}).inject(self.el);

				createTooltip(self.options.description[1]).inject(hint, 'top');
			}
			else {
				new Element('p.formHint', {
					'html': self.options.description || ''
				}).inject(self.el)
			}
		}
	},

	afterInject: function(){
	},

	// Element has changed, do something
	changed: function(){
		var self = this;

		if(self.getValue() != self.previous_value){
			if(self.save_on_change){
				if(self.changed_timer) clearTimeout(self.changed_timer);
				self.changed_timer = self.save.delay(300, self);
			}
			self.fireEvent('change')
		}

	},

	save: function(){
		var self = this;

		Api.request('settings.save', {
			'data': {
				'section': self.section,
				'name': self.name,
				'value': self.getValue()
			},
			'useSpinner': true,
			'spinnerOptions': {
				'target': self.el
			},
			'onComplete': self.saveCompleted.bind(self)
		});

	},

	saveCompleted: function(json){
		var self = this;

		var sc = json.success ? 'save_success' : 'save_failed';

		self.previous_value = self.getValue();
		self.el.addClass(sc);

		(function(){
			self.el.removeClass(sc);
		}).delay(3000, self);
	},

	setName: function(name){
		this.name = name;
	},

	postName: function(){
		var self = this;
		return self.section + '[' + self.name + ']';
	},

	getValue: function(){
		var self = this;
		return self.input.get('value');
	},

	getSettingValue: function(){
		return this.value;
	},

	inject: function(el, position){
		this.el.inject(el, position);
		return this.el;
	},

	toElement: function(){
		return this.el;
	}
});

var Option = {};
Option.String = new Class({
	Extends: OptionBase,

	type: 'string',

	create: function(){
		var self = this;

		self.el.adopt(
			self.createLabel(),
			self.input = new Element('input.inlay', {
				'type': 'text',
				'name': self.postName(),
				'value': self.getSettingValue(),
				'placeholder': self.getPlaceholder()
			})
		);
	},

	getPlaceholder: function(){
		return this.options.placeholder
	}
});

Option.Dropdown = new Class({
	Extends: OptionBase,

	create: function(){
		var self = this;

		self.el.adopt(
			self.createLabel(),
			self.input = new Element('select', {
				'name': self.postName()
			})
		);

		Object.each(self.options.values, function(value){
			new Element('option', {
				'text': value[0],
				'value': value[1]
			}).inject(self.input)
		});

		self.input.set('value', self.getSettingValue());

		var dd = new Form.Dropdown(self.input, {
			'onChange': self.changed.bind(self)
		});
		self.input = dd.input;
	}
});

Option.Checkbox = new Class({
	Extends: OptionBase,

	type: 'checkbox',

	create: function(){
		var self = this;

		var randomId = 'r-' + randomString();

		self.el.adopt(
			self.createLabel().set('for', randomId),
			self.input = new Element('input.inlay', {
				'name': self.postName(),
				'type': 'checkbox',
				'checked': self.getSettingValue(),
				'id': randomId
			})
		);

		new Form.Check(self.input);

	},

	getValue: function(){
		var self = this;
		return +self.input.checked;
	}
});

Option.Password = new Class({
	Extends: Option.String,
	type: 'password',

	create: function(){
		var self = this;

		self.el.adopt(
			self.createLabel(),
			self.input = new Element('input.inlay', {
				'type': 'text',
				'name': self.postName(),
				'value': self.getSettingValue() ? '********' : '',
				'placeholder': self.getPlaceholder()
			})
		);

		self.input.addEvent('focus', function(){
			self.input.set('value', '');
			self.input.set('type', 'password');
		})

	}
});

Option.Bool = new Class({
	Extends: Option.Checkbox
});

Option.Enabler = new Class({
	Extends: Option.Bool,

	create: function(){
		var self = this;

		self.el.adopt(
			self.input = new Element('input.inlay', {
				'type': 'checkbox',
				'checked': self.getSettingValue(),
				'id': 'r-'+randomString()
			})
		);

		new Form.Check(self.input);
	},

	changed: function(){
		this.parent();
		this.checkState();
	},

	checkState: function(){
		var self = this,
			enabled = self.getValue();

		self.parentFieldset[ enabled ? 'removeClass' : 'addClass']('disabled');

		if(self.parentList)
			self.parentFieldset.inject(self.parentList.getElement('h3'), enabled ? 'before' : 'after');

	},

	afterInject: function(){
		var self = this;

		self.parentFieldset = self.el.getParent('fieldset').addClass('enabler');
		self.parentList = self.parentFieldset.getParent('.option_list');
		self.el.inject(self.parentFieldset, 'top');
		self.checkState()
	}

});

Option.Int = new Class({
	Extends: Option.String
});

Option.Float = new Class({
	Extends: Option.Int
});

Option.Directory = new Class({

	Extends: OptionBase,

	type: 'span',
	browser: null,
	save_on_change: false,
	use_cache: false,
	current_dir: '',

	create: function(){
		var self = this;

		self.el.adopt(
			self.createLabel(),
			self.directory_inlay = new Element('span.directory.inlay', {
				'events': {
					'click': self.showBrowser.bind(self)
				}
			}).adopt(
				self.input = new Element('input', {
					'value': self.getSettingValue(),
					'events': {
						'change': self.filterDirectory.bind(self),
						'keydown': function(e){
							if(e.key == 'enter' || e.key == 'tab')
								(e).stop();
						},
						'keyup': self.filterDirectory.bind(self),
						'paste': self.filterDirectory.bind(self)
					}
				})
			)
		);

		self.cached = {};
	},

	filterDirectory: function(e){
		var self = this,
			value = self.getValue(),
			path_sep = Api.getOption('path_sep'),
			active_selector = 'li:not(.blur):not(.empty)';

		if(e.key == 'enter' || e.key == 'tab'){
			(e).stop();

			var first = self.dir_list.getElement(active_selector);
			if(first){
				self.selectDirectory(first.get('data-value'));
			}
		}
		else {

			// New folder
			if(value.substr(-1) == path_sep){
				if(self.current_dir != value)
					self.selectDirectory(value)
			}
			else {
				var pd = self.getParentDir(value);
				if(self.current_dir != pd)
					self.getDirs(pd);

				var folder_filter = value.split(path_sep).getLast()
				self.dir_list.getElements('li').each(function(li){
					var  valid = li.get('text').substr(0, folder_filter.length).toLowerCase() != folder_filter.toLowerCase()
					li[valid ? 'addClass' : 'removeClass']('blur')
				});

				var first = self.dir_list.getElement(active_selector);
				if(first){
					if(!self.dir_list_scroll)
						self.dir_list_scroll = new Fx.Scroll(self.dir_list, {
							'transition': 'quint:in:out'
						});

					self.dir_list_scroll.toElement(first);
				}
			}
		}
	},

	selectDirectory: function(dir){
		var self = this;

		self.input.set('value', dir);

		self.getDirs()
	},

	previousDirectory: function(){
		var self = this;

		self.selectDirectory(self.getParentDir())
	},

	caretAtEnd: function(){
		var self = this;

		self.input.focus();

		if (typeof self.input.selectionStart == "number") {
			self.input.selectionStart = self.input.selectionEnd = self.input.get('value').length;
		} else if (typeof el.createTextRange != "undefined") {
			self.input.focus();
			var range = self.input.createTextRange();
			range.collapse(false);
			range.select();
		}
	},

	showBrowser: function(){
		var self = this;

		// Move caret to back of the input
		if(!self.browser || self.browser && !self.browser.isVisible())
			self.caretAtEnd()

		if(!self.browser){
			self.browser = new Element('div.directory_list').adopt(
				new Element('div.pointer'),
				new Element('div.actions').adopt(
					self.back_button = new Element('a.back', {
						'html': '',
						'events': {
							'click': self.previousDirectory.bind(self)
						}
					}),
					new Element('label', {
						'text': 'Hidden folders'
					}).adopt(
						self.show_hidden = new Element('input[type=checkbox].inlay', {
							'events': {
								'change': function(){
									self.getDirs()
								}
							}
						})
					)
				),
				self.dir_list = new Element('ul', {
					'events': {
						'click:relay(li:not(.empty))': function(e, el){
							(e).preventDefault();
							self.selectDirectory(el.get('data-value'))
						},
						'mousewheel': function(e){
							(e).stopPropagation();
						}
					}
				}),
				new Element('div.actions').adopt(
					new Element('a.clear.button', {
						'text': 'Clear',
						'events': {
							'click': function(e){
								self.input.set('value', '');
								self.hideBrowser(e, true);
							}
						}
					}),
					new Element('a.cancel', {
						'text': 'Cancel',
						'events': {
							'click': self.hideBrowser.bind(self)
						}
					}),
					new Element('span', {
						'text': 'or'
					}),
					self.save_button = new Element('a.button.save', {
						'text': 'Save',
						'events': {
							'click': function(e){
								self.hideBrowser(e, true)
							}
						}
					})
				)
			).inject(self.directory_inlay, 'before');

			new Form.Check(self.show_hidden);
		}

		self.initial_directory = self.input.get('value');

		self.getDirs();
		self.browser.show();
		self.el.addEvent('outerClick', self.hideBrowser.bind(self))
	},

	hideBrowser: function(e, save){
		var self = this;
		(e).preventDefault();

		if(save)
			self.save();
		else
			self.input.set('value', self.initial_directory);

		self.browser.hide();
		self.el.removeEvents('outerClick')

	},

	fillBrowser: function(json){
		var self = this,
			v = self.getValue();

		self.data = json;

		var previous_dir = json.parent;

		if(v == '')
			self.input.set('value', json.home);

		if(previous_dir.length >= 1 && !json.is_root){

			var prev_dirname = self.getCurrentDirname(previous_dir);
			if(previous_dir == json.home)
				prev_dirname = 'Home Folder';
			else if(previous_dir == '/' && json.platform == 'nt')
				prev_dirname = 'Computer';

			self.back_button.set('data-value', previous_dir);
			self.back_button.set('html', '&laquo; ' + prev_dirname);
			self.back_button.show()
		}
		else {
			self.back_button.hide()
		}

		if(self.use_cache)
			if(!json)
				json = self.cached[v];
			else
				self.cached[v] = json;

		self.dir_list.empty();
		if(json.dirs.length > 0)
			json.dirs.each(function(dir){
				new Element('li', {
					'data-value': dir,
					'text': self.getCurrentDirname(dir)
				}).inject(self.dir_list)
			});
		else
			new Element('li.empty', {
				'text': 'Selected folder is empty'
			}).inject(self.dir_list)

		//fix for webkit type browsers to refresh the dom for the file browser
		//http://stackoverflow.com/questions/3485365/how-can-i-force-webkit-to-redraw-repaint-to-propagate-style-changes
		self.dir_list.setStyle('webkitTransform', 'scale(1)');
		self.caretAtEnd();
	},

	getDirs: function(dir){
		var self = this,
			c = dir || self.getValue();

		if(self.cached[c] && self.use_cache){
			self.fillBrowser()
		}
		else {
			Api.request('directory.list', {
				'data': {
					'path': c,
					'show_hidden': +self.show_hidden.checked
				},
				'onComplete': function(json){
					self.current_dir = c;
					self.fillBrowser(json);
				}
			})
		}
	},

	getParentDir: function(dir){
		var self = this;

		if(!dir && self.data && self.data.parent)
			return self.data.parent;

		var v = dir || self.getValue();
		var sep = Api.getOption('path_sep');
		var dirs = v.split(sep);
		if(dirs.pop() == '')
			dirs.pop();

		return dirs.join(sep) + sep
	},

	getCurrentDirname: function(dir){
		var dir_split = dir.split(Api.getOption('path_sep'));

		return dir_split[dir_split.length-2] || Api.getOption('path_sep')
	},

	getValue: function(){
		var self = this;
		return self.input.get('value');
	}
});



Option.Directories = new Class({

	Extends: Option.String,

	directories: [],
	delimiter: '::',

	afterInject: function(){
		var self = this;

		self.el.setStyle('display', 'none');

		self.directories = [];
		self.getValue().split(self.delimiter).each(function(value){
			self.addDirectory(value);
		});
		self.addDirectory();

	},

	addDirectory: function(value){
		var self = this;

		var has_empty = false;
		self.directories.each(function(dir){
			if(!dir.getValue())
				has_empty = true;
		});
		if(has_empty) return;

		var dir = new Option.Directory(self.section, self.name, value || '', self.options);

		var parent = self.el.getParent('fieldset');
		var dirs = parent.getElements('.multi_directory');
		if(dirs.length == 0)
			$(dir).inject(parent);
		else
			$(dir).inject(dirs.getLast(), 'after');

		// Replace some properties
		dir.save = self.saveItems.bind(self);
		$(dir).getElement('label').set('text', 'Movie Folder');
		$(dir).getElement('.formHint').destroy();
		$(dir).addClass('multi_directory');

		if(!value)
			$(dir).addClass('is_empty');

		// Add remove button
		new Element('a.icon2.delete', {
			'events': {
				'click': self.delItem.bind(self, dir)
			}
		}).inject(dir);

		self.directories.include(dir);

	},

	delItem: function(dir){
		var self = this;
		self.directories.erase(dir);

		$(dir).destroy();

		self.saveItems();
		self.addDirectory();
	},

	saveItems: function(){
		var self = this;

		var dirs = [];
		self.directories.each(function(dir){
			if(dir.getValue()){
				$(dir).removeClass('is_empty');
				dirs.include(dir.getValue());
			}
			else
				$(dir).addClass('is_empty');
		});

		self.input.set('value', dirs.join(self.delimiter));
		self.input.fireEvent('change');

		self.addDirectory();

	}


});

Option.Choice = new Class({
	Extends: Option.String,

	afterInject: function(){
		var self = this;

		self.tags = [];
		self.replaceInput();

		self.select = new Element('select').adopt(
			new Element('option[text=Add option]')
		).inject(self.tag_input, 'after');

		var o = self.options.options;
		Object.each(o.choices, function(label, choice){
			new Element('option', {
				'text': label,
				'value': o.pre + choice + o.post
			}).inject(self.select);
		});

		self.select = new Form.Dropdown(self.select, {
			'onChange': self.addSelection.bind(self)
		});
	},

	replaceInput: function(){
		var self = this;
		self.initialized = self.initialized ? self.initialized+1 : 1;

		var value = self.getValue();
		var matches = value.match(/<([^>]*)>/g);

		self.tag_input = new Element('ul.inlay', {
			'events': {
				'click': function(e){
					if(e.target == self.tag_input){
						var input = self.tag_input.getElement('li:last-child input');
						input.fireEvent('focus');
						input.focus();
						input.setCaretPosition(input.get('value').length);
					}

					self.el.addEvent('outerClick', function(){
						self.reset();
						self.el.removeEvents('outerClick');
					})
				}
			}
		}).inject(self.input, 'after');
		self.el.addClass('tag_input');

		var mtches = [];
		if(matches)
			matches.each(function(match, mnr){
				var pos = value.indexOf(match),
					msplit = [value.substr(0, pos), value.substr(pos, match.length), value.substr(pos+match.length)];

				msplit.each(function(matchsplit, snr){
					if(msplit.length-1 == snr){
						value = matchsplit;

						if(matches.length-1 == mnr)
							mtches.append([value]);

						return;
					}
					mtches.append([value == matchsplit ? match : matchsplit]);
				});
			});

		if(mtches.length == 0 && value != '')
			mtches.include(value);

		mtches.each(self.addTag.bind(self));

		self.addLastTag();

		// Sortable
		self.sortable = new Sortables(self.tag_input, {
			'revert': true,
			'handle': '',
			'opacity': 0.5,
			'onComplete': function(){
				self.setOrder();
				self.reset();
			}
		});

		// Calc width on show
		var input_group = self.tag_input.getParent('.tab_content');
		input_group.addEvent('activate', self.setAllWidth.bind(self));
	},

	addLastTag: function(){
		if(this.tag_input.getElement('li.choice:last-child') || !this.tag_input.getElement('li'))
			this.addTag('');
	},

	addTag: function(tag){
		var self = this;
		tag = new Option.Choice.Tag(tag, {
			'onChange': self.setOrder.bind(self),
			'onBlur': function(){
				self.addLastTag();
			},
			'onGoLeft': function(){
				self.goLeft(this)
			},
			'onGoRight': function(){
				self.goRight(this)
			}
		});
		$(tag).inject(self.tag_input);

		if(self.initialized > 1)
			tag.setWidth();
		else
			(function(){ tag.setWidth(); }).delay(10, self);

		self.tags.include(tag);

		return tag;
	},

	goLeft: function(from_tag){
		var self = this;

		from_tag.blur();

		var prev_index = self.tags.indexOf(from_tag)-1;
		if(prev_index >= 0)
			self.tags[prev_index].selectFrom('right');
		else
			from_tag.focus();

	},
	goRight: function(from_tag){
		var self = this;

		from_tag.blur();

		var next_index = self.tags.indexOf(from_tag)+1;
		if(next_index < self.tags.length)
			self.tags[next_index].selectFrom('left');
		else
			from_tag.focus();
	},

	setOrder: function(){
		var self = this;

		var value = '';
		self.tag_input.getElements('li').each(function(el){
			value += el.getElement('span').get('text');
		});
		self.addLastTag();

		self.input.set('value', value);
		self.input.fireEvent('change');
		self.setAllWidth();
	},

	addSelection: function(){
		var self = this;

		var tag = self.addTag(self.el.getElement('.selection input').get('value'));
		self.sortable.addItems($(tag));
		self.setOrder();
		self.setAllWidth();
	},

	reset: function(){
		var self = this;

		self.tag_input.destroy();
		self.sortable.detach();

		self.replaceInput();
		self.setAllWidth();
	},

	setAllWidth: function(){
		var self = this;
		self.tags.each(function(tag){
			tag.setWidth.delay(10, tag);
		});
	}

});

Option.Choice.Tag = new Class({

	Implements: [Options, Events],

	options: {
		'pre': '<',
		'post': '>'
	},

	initialize: function(tag, options){
		var self = this;
		self.setOptions(options);

		self.tag = tag;
		self.is_choice = tag.substr(0, 1) == self.options.pre && tag.substr(-1) == self.options.post;

		self.create();
	},

	create: function(){
		var self = this;

		self.el =  new Element('li', {
			'class': self.is_choice ? 'choice' : '',
			'styles': {
				'border': 0
			},
			'events': {
				'mouseover': !self.is_choice ? self.fireEvent.bind(self, 'focus') : function(){}
			}
		}).adopt(
			self.input = new Element(self.is_choice ? 'span' : 'input', {
				'text': self.tag,
				'value': self.tag,
				'styles': {
					'width': 0
				},
				'events': {
					'keyup': self.is_choice ? null : function(e){
						var current_caret_pos = self.input.getCaretPosition();
						if(e.key == 'left' && current_caret_pos == self.last_caret_pos){
							self.fireEvent('goLeft');
						}
						else if(e.key == 'right' && self.last_caret_pos === current_caret_pos){
							self.fireEvent('goRight');
						}
						self.last_caret_pos = self.input.getCaretPosition();

						self.setWidth();
						self.fireEvent('change');
					},
					'focus': self.fireEvent.bind(self, 'focus'),
					'blur': self.fireEvent.bind(self, 'blur')
				}
			}),
			self.span = !self.is_choice ? new Element('span', {
				'text': self.tag
			}) : null,
			self.del_button = new Element('a.delete', {
				'events': {
					'click': self.del.bind(self)
				}
			})
		);

		self.addEvent('focus', self.setWidth.bind(self));

	},

	blur: function(){
		var self = this;

		self.input.blur();

		self.selected = false;
		self.el.removeClass('selected');
		self.input.removeEvents('outerClick');
	},

	focus: function(){
		var self = this;
		if(!self.is_choice){
			this.input.focus();
		}
		else {
			if(self.selected) return;
			self.selected = true;
			self.el.addClass('selected');
			self.input.addEvent('outerClick', self.blur.bind(self));

			var temp_input = new Element('input', {
				'events': {
					'keydown': function(e){
						e.stop();

						if(e.key == 'right'){
							self.fireEvent('goRight');
							this.destroy();
						}
						else if(e.key == 'left'){
							self.fireEvent('goLeft');
							this.destroy();
						}
						else if(e.key == 'backspace'){
							self.del();
							this.destroy();
							self.fireEvent('goLeft');
						}
					}
				},
				'styles': {
					'height': 0,
					'width': 0,
					'position': 'absolute',
					'top': -200
				}
			});
			self.el.adopt(temp_input);
			temp_input.focus();
		}
	},

	selectFrom: function(direction){
		var self = this;

		if(!direction || self.is_choice){
			self.focus();
		}
		else {
			self.focus();
			var position = direction == 'left' ? 0 : self.input.get('value').length;
			self.input.setCaretPosition(position);
		}

	},

	setWidth: function(){
		var self = this;

		if(self.span && self.input){
			self.span.set('text', self.input.get('value'));
			self.input.setStyle('width', self.span.getSize().x+2);
		}
	},

	del: function(){
		var self = this;
		self.el.destroy();
		self.fireEvent('change');
	},

	getValue: function(){
		return this.span.get('text');
	},

	toElement: function(){
		return this.el;
	}

});

Option.Combined = new Class({

	Extends: Option.String,

	afterInject: function(){
		var self = this;

		self.fieldset = self.input.getParent('fieldset');
		self.combined_list = new Element('div.combined_table').inject(self.fieldset.getElement('h2'), 'after');
		self.values = {};
		self.inputs = {};
		self.items = [];
		self.labels = {};
		self.descriptions = {};

		self.options.combine.each(function(name){

			self.inputs[name] = self.fieldset.getElement('input[name='+self.section+'['+name+']]');
			var values = self.inputs[name].get('value').split(',');

			values.each(function(value, nr){
				if(!self.values[nr]) self.values[nr] = {};
				self.values[nr][name] = value.trim();
			});

			self.inputs[name].getParent('.ctrlHolder').setStyle('display', 'none');
			self.inputs[name].addEvent('change', self.addEmpty.bind(self))

		});

		var head = new Element('div.head').inject(self.combined_list);

		Object.each(self.inputs, function(input, name){
			var _in = input.getNext();
			self.labels[name] = input.getPrevious().get('text');
			self.descriptions[name] = _in ? _in.get('text') : '';

			new Element('abbr', {
				'class': name,
				'text': self.labels[name],
				'title': self.descriptions[name]
			}).inject(head)
		});


		Object.each(self.values, function(item){
			self.createItem(item);
		});

		self.addEmpty();

	},

	add_empty_timeout: 0,
	addEmpty: function(){
		var self = this;

		if(self.add_empty_timeout) clearTimeout(self.add_empty_timeout);

		var has_empty = 0;
		self.items.each(function(ctrl_holder){
			var empty_count = 0;
			self.options.combine.each(function(name){
				var input = ctrl_holder.getElement('input.' + name);
				if(input.get('value') == '' || input.get('type') == 'checkbox')
					empty_count++
			});
			has_empty += (empty_count == self.options.combine.length) ? 1 : 0;
			ctrl_holder[(empty_count == self.options.combine.length) ? 'addClass' : 'removeClass']('is_empty');
		});
		if(has_empty > 0) return;

		self.add_empty_timeout = setTimeout(function(){
			self.createItem({'use': true});
		}, 10);
	},

	createItem: function(values){
		var self = this;

		var item = new Element('div.ctrlHolder').inject(self.combined_list),
			value_count = 0,
			value_empty = 0;

		self.options.combine.each(function(name){
			var value = values[name] || '';

			if(name.indexOf('use') != -1){
				var checkbox = new Element('input[type=checkbox].inlay.'+name, {
					'checked': +value,
					'events': {
						'click': self.saveCombined.bind(self),
						'change': self.saveCombined.bind(self)
					}
				}).inject(item);

				new Form.Check(checkbox);
			}
			else {
				value_count++;
				new Element('input[type=text].inlay.'+name, {
					'value': value,
					'placeholder': self.labels[name] || name,
					'events': {
						'keyup': self.saveCombined.bind(self),
						'change': self.saveCombined.bind(self)
					}
				}).inject(item);

				if(!value)
					value_empty++;
			}


		});

		item[value_empty == value_count ? 'addClass' : 'removeClass']('is_empty');

		new Element('a.icon2.delete', {
			'events': {
				'click': self.deleteCombinedItem.bind(self)
			}
		}).inject(item);

		self.items.include(item);


	},

	saveCombined: function(){
		var self = this;


		var temp = {};
		self.items.each(function(item, nr){
			self.options.combine.each(function(name){
				var input = item.getElement('input.'+name);
				if(item.hasClass('is_empty')) return;

				if(!temp[name]) temp[name] = [];
				temp[name][nr] = input.get('type') == 'checkbox' ? +input.get('checked') : input.get('value').trim();

			})
		});

		self.options.combine.each(function(name){
			self.inputs[name].set('value', (temp[name] || []).join(','));
			self.inputs[name].fireEvent('change');
		});

		self.addEmpty()

	},

	deleteCombinedItem: function(e){
		var self = this;
		(e).preventDefault();

		var item = e.target.getParent();

		self.items.erase(item);
		item.destroy();

		self.saveCombined();
	}

});

var createTooltip = function(description){

	var tip = new Element('div.tooltip', {
			'events': {
				'mouseenter': function(){
					tip.addClass('shown')
				},
				'mouseleave': function(){
					tip.removeClass('shown')
				}
			}
		}).adopt(
			new Element('a.icon2.info'),
			new Element('div.tip', {
				'html': description
			})
		);

	return tip;
};
