var dropdown = {

    container : $('dropdown'),
    blocker : false,

    // events
    onOpen   : $empty,
    onClose  : $empty,
    onSubmit : $empty,

    preloader : new Loader({
				'onStart' : function() {
						new Element('div').set('id', 'dropdown-preloader').inject(document.body);
				},
				'onStop' : function() {
						if($('dropdown-preloader')) $('dropdown-preloader').destroy();
				}
		}),
		
		loader : new Loader({
				'onStart' : function(msg) {

						var l = new Element('div')
								.set('id', 'dropdown-loader')
								.set('html', '<p>' + msg + '…</p>')
								.inject('dropdown-content', 'before').fadeIn(200);

				},
				'onStop' : function() {
						if($('dropdown-loader')) $('dropdown-loader').destroy();
				}
		}),

		open : function(url) {

				var parsed = url.replace(/^\//, '').split('/');
				var scroll = $(document.body).getScroll().y;
				var view   = parsed[0];

				// clean up before we start a new dropdown
				this.clean(view);
				this.preloader.start();							

				// call the onOpen user event
				this.onOpen.attempt();

				// hide all quicktime videos
				if(!Browser.Engine.webkit) $$('.quicktime').hide();		

				// add the blocker if it is not there
				if(!this.blocker) this.blocker = new Element('div', {id : 'blocker'})
						.addClass('blocker')
						.addClass('dropdown')
						.addEvent('click', this.close.bind(this))
						.inject(document.body);

				// add the dropdown container if it is not there			
				if(!this.container) this.container = new Element('div').set('id', 'dropdown').addClass('ajax').inject(document.body);

				// late css loader
				if(!$(this.view + '-css')) new Asset.css('/app/views/' + this.view + '/styles.css?v=' + $time(), {id : this.view + '-css'});
				
				// pull up 
				this.container.setStyle('top', -6000);
				this.container.set('load', {
						method : 'get',
						evalScripts : true,
						onComplete : function() {
                
                // move in
								dropdown.container.setStyle('top', -dropdown.container.getHeight())
								dropdown.container.set('tween', {duration : 150}).tween('top', 0);
        				dropdown.preloader.stop();							
                
                dropdown.register();
								dropdown.focus();
								window.scrollTo(0, scroll);

						}
				}).load(url);
						
		},

    register : function() {
        $('dropdown-content').getElements('.tab').each(function(t) {
            var id = t.get('id').replace('dropdown-tab-', '');
            dropdown.callback(id, 'load', this);                				
    		}, this);
    },

		clean : function(view) {
				if(view == this.view) return true;
		    if($(this.view + '-css')) $(this.view + '-css').destroy();
				this.view = view;
		},
    
		kill : function() {
				this.container.destroy();
				this.container = false;
				if(this.blocker) this.blocker.destroy();		
				this.blocker = false;
				this.onClose.attempt();
		},

		close : function() {
				this.onClose.attempt();
				if(this.loader.loading) return false;
				if(!this.container) return false;
        if(this.container.hasClass('html')) return window.close();
				this.container.set('tween', {
						duration : 200,
						onComplete : function(element) {
								this.container.destroy();
								this.container = false;
								if(!window.webkit) $$('.quicktime').removeClass('hide');		
						}.bind(this)
				}).tween('top', -this.container.getHeight());
				if(this.blocker) this.blocker.destroy();
				this.blocker = false;
		},

    showTab : function(id) {

        this.hideMSG();

        if(this.loader.loading) return false;

				$('dropdown-menu').getElements('li.active').removeClass('active');
				$('dropdown-menu-' + id).addClass('active');

				$$('.tab').removeClass('active');
				
				var tab = $('dropdown-tab-' + id);
				if(tab) tab.addClass('active');
    
        this.focus();
				this.callback(id, 'focus', id);
    
    },

		showMSG : function(msg, type) {

				this.hideMSG();
        
        $('dropdown').addClass('msg');
				
				var m = new Element('div')
						.set('id', 'dropdown-msg')
						.set('html', '<p>' + msg + '</p>')
						.addClass(type)
						.addEvent('click', this.hideMSG.bind(this))
						.inject('dropdown-content', 'before');
		
				return m;
		
		},

		hideMSG : function() {

        $('dropdown').removeClass('msg');

				if(this.timer) $clear(this.timer);
				if($('dropdown-msg')) $('dropdown-msg').destroy();
		},

    showError : function(msg) {
				dropdown.showMSG(msg, 'error');
				dropdown.focus();
    },
    
    showSuccess : function(msg) {
    		dropdown.showMSG(msg, 'success');
				dropdown.timer = dropdown.hideMSG.delay(2000);
    },

		showQuestion : function(msg, callback) {

				var m = this.showMSG(msg, 'question');
				var b = new Element('div').addClass('buttons').inject(m);

				var no = new Element('a')
						.set('href', './')
						.set('text','no')
						.addEvent('click', function(e) {
								e.stop();
								dropdown.hideMSG();								
						})
						.inject(b)

				var yes = new Element('a')
						.set('href', './')
						.set('text', 'yes')
						.addEvent('click', function(e) {
								e.stop();
								dropdown.hideMSG();								
								if(callback) callback.attempt();
						})
						.inject(b)
										
		},

    focus : function(field) {
				var element = (field) ? this.field(field) : this.container.getElement('.tab.active .focus');
				if(element) element.focus();    
    },

    field : function(name) {
    		return this.container.getElement('.tab.active [name=' + name + ']');
    },

    value : function(name) {
    		var field = this.field(name);
    		return (field) ? field.get('value') : false;
    },

    submit : function() {
        
        var form = this.container.getElement('form.active');

        if(!form) return false;        
        if(this.loader.loading) return false;

				this.hideMSG();

				var id  = form.get('id').replace('dropdown-tab-', '');
				var msg = (form.getElement('[name=loading]')) ? form.getElement('[name=loading]').value : 'Please, wait a second…';
        				
        if(this.callback(id, 'validate', form) === false) return false;				

				this.loader.start(msg);
				
				form.set('send', {
						onComplete : function(response) {
								
								r = JSON.decode(response, true);
								if(!r) return alert(response);
								
								if(r.status == 'error') {
    								dropdown.loader.stop();
								    return dropdown.showError(r.msg);
								}

                dropdown.callback(id, 'submit', r);
								dropdown.onSubmit.attempt({view : dropdown.view, tab : id, response : r}, dropdown);
								
								if(!dropdown.callback(id, 'close', form)) {
    								dropdown.loader.stop();
								    return true;
								}

                dropdown.loader.stop();
								dropdown.close();
								
						}    		

    		}).send();

    },
    
    callback : function(id, func, args) {                     
        return (dropdown[id] && dropdown[id][func]) ? dropdown[id][func].attempt(args, dropdown) : -1;
    }
    
};



/* Upload */
var Upload = new Class({

	Implements : [Options, Events],

	initialize : function(form, options) {
			
			var self = this;
			
			this.setOptions(options)
			this.form = $(form);
			this.file = this.form.getElement('input[type=file]');
									
			this.form.addEvent('submit', function(e) {
					
					if(self.file.value.clean().length == 0) {
							e.stop();
							self.fireEvent('onError',self.file.get('title'));
							return false;
					}
									
					self.fireEvent('onStart', this);
					self.form.set('target', self.frame());
					self.keepAlive();
					return true;
					
			});
			
	},

	frame : function() {

 			var self = this;
			var id = 'f' + Math.floor(Math.random() * 99999);
			var iframe = new Element('iframe')
				.setStyle('display', 'none')
				.set('src', 'about:blank')
				.set('id', id)
				.set('name', id)
				.addEvent('load', function(e) {
																					
						if(this.contentDocument) {
								var d = this.contentDocument;
						} else if(this.contentWindow) {
								var d = this.contentWindow.document;
						} else {
								var d = window.frames[id].document;
						}

						if(d.location.href == "about:blank") return;
						self.file.value = '';
						self.fireEvent('onComplete', JSON.decode($(d.body).get('html'), true));
						this.destroy();
						
				})
				.inject(document.body);
	
			return id;
			
	},
	
	keepAlive : function() {
		  if(Browser.Engine.webkit) new Request({url : '/close', method : 'get'}).send();	
	}
    
});









/* ZooBox */
var ZooBox = new Class({

		Implements : Events,
		
		initialize : function(element) {
				this.tags = [];
				this.counter = 0;
				this.back = false;
				this.stop = false;
				this.element = $(element);
        this.input = new Element('input').set('type', 'text');
				this.setup();							
		},
					
		getSelectionStart : function(o) {
				if(o.createTextRange) {
						var r = document.selection.createRange().duplicate();
						r.moveEnd('character', o.value.length);
						if (r.text == '') return o.value.length;
						return o.value.lastIndexOf(r.text);
				} else {
				    return o.selectionStart;
				}
		},

		setup : function() {

				var that = this;
				
				this.box = new Element('ul')
						.addClass('tagbox')
						.injectBefore(this.element)
						.addEvent('click', function(e) {
								var block = ['span', 'li'];
								if(!block.contains(e.target.get('tag'))) that.input.focus();	
						});

				this.element.setProperty('type', 'hidden');

				var li = new Element('li').addClass('new').inject(this.box);

				this.input.inject(li);
				this.input.addEvents({
								'keydown' : function(event) {
										
										switch(event.key) {
												case 'enter':
														event.stop();
														that.add();						
														that.fireEvent('onEnter');				
														break;
												case 'tab':
												    event.stop();
														that.add();
														break;
										}
																				
								}, 
								'keyup' : function(event) {
										
										var width = that.input.value.length*10;
										if(width < 50) width = 50;
										that.input.setStyle('width', width + 'px');
										that.position = that.getSelectionStart(that.input);																								

										if(event.code == 188) {
												event.stop();
												that.add();
										}

										switch(event.key) {
												case 'backspace':
												    event.preventDefault();
														if(that.position == 0 && that.back == true) {
																that.input.blur()
																that.last()
																that.back = false;
														} else if(that.position == 0) that.back = true;														
														break;
												case 'left':
														if(that.position == 0) {
																that.input.blur()
																that.last()
																that.back = false;
														}
														break;
												case 'right':
														if(that.position == that.input.value.length && that.position != 0) that.add();
														break;
										}		
										
								}.bind(this),
								'focus': function() {
										this.input.addClass('active');
										if(this.selected()) this.selected().removeClass('selected');				
								}.bind(this),
								'blur': function() {
										this.input.removeClass('active');
										this.position = 0;
								}.bind(this)
						});

				this.preload();
		},

		focus : function() {
				this.input.focus();
		},

		restore : function() {
				this.tags = [];
				this.box.getElements('li').each(function(li) {
						if(!li.hasClass('new')) li.destroy();
				});
		},

		preload : function() {
				/* preload all existing tags */
				this.element.value.split(',').each(function(t) {
						this.add(t.clean());						
				}.bind(this));
		},
			
		getTag : function(tag) {
				if(!tag) var tag = this.input.get('value');
				return tag.clean().toLowerCase().replace(',','').replace(';','');
		},
								
		add : function(tag, replace) {

				this.fireEvent('onBeforeAdd');

				var tag = this.getTag(tag);
				
				if(tag.length < 2 || this.stop) return this.input.focus();

		    if(this.tags.contains(tag)) {
		        this.input.focus();
		        return dropdown.showError('You\'ve already added this one!');
		    }
		
				this.tags.push(tag);

				var li = new Element('li')
						.set('rel', tag.replace(' ', '-'))
						.injectBefore(this.input.getParent());

				var name   = new Element('span').addClass('tag').set('text', tag).inject(li);
				var remove = new Element('span').addClass('delete').inject(name);
				var field  = new Element('input').set('type', 'text').addClass('field').inject(li);
		
				this.input.set('value', '');
				this.activate(li, remove, field);
				this.element.set('value', this.serialize());
				
				this.fireEvent('onAdd', tag);
				this.input.focus();
				
		},
		activate : function(element, remove, field) {

				element.addEvent('click', this.select.bind(this, element));

				remove.addEvent('click', function() {
						this.select(element);
						this.remove();
				}.bind(this));

				field.addEvent('keyup', function(event) {
						if(field.value.length > 0) field.set('value', '');
						
						switch(event.key) {
								case 'left': 
										this.previous();
										break;
								case 'backspace':
										this.remove();
										break;
								case 'right':
										this.next();
										break;		
						}
						
				}.bind(this));
		},
		remove : function(tag) {				
				if(!this.selected()) return false;
				var selected = this.selected();
				var tag 		 = selected.get('text').trim();
				var index    = this.tags.indexOf(tag);
				this.previous();
				this.tags.erase(tag);
				if(this.tags.length == 0) this.input.focus();
				if(index == 0) this.next();
				selected.destroy();
				this.element.value = this.serialize();
				this.fireEvent('onRemove', tag);
				this.stop = false;	
				dropdown.hideMSG();
		},
		removeByTag : function(tag) {
				var element = this.box.getElement('[rel=' + tag + ']');
				if(!element) return false;
				this.select(element);
				this.remove();
				this.selected().removeClass('selected');
				this.focus();				
		},
		selected : function() {
				return this.box.getElement('.selected');
		},
		select : function(element) {
				this.fireEvent('onSelect');
				if(this.selected()) this.selected().removeClass('selected');
				if(!$(element)) return false;
				element.addClass('selected');
				element.getElement('input.field').focus();
		},
		previous : function() {
				this.fireEvent('reset');
				if(!this.selected()) return false;
				var previous = this.selected().getPrevious();
				if(previous) this.select(previous);
		},
		next : function() {
				this.fireEvent('reset');
				if(!this.selected()) return false;
				var next = this.selected().getNext();
				(next && !next.hasClass('new')) ? this.select(next) : this.input.focus();
		},
		last : function() {
				var last = this.input.getParent().getPrevious();
				if(!last) return this.input.focus();
				this.select(last);
		},
		first : function() {
				var first = this.box.getElement('li');
				if(!first || first.hasClass('new')) return false;
				this.select(first);
		},
		serialize : function() {
				var output = '';
				var seperator = '';
				this.box.getElements('li').each(function(el) {
						if(el.hasClass('new')) return false;
						output += seperator + el.get('text').clean();
						seperator = ',';
				});
				return output;
		}
});





/* Autocomplete */
var ZooAutocomplete = new Class({		

		Extends : ZooBox,
		Implements : Options,

    data : [],

		options : {
				uid : 'tags',
				maxtags : 50,
				maxresults : 10,
				maxalert : 'You can\'t add more tags',
				offset : {
						x : 0,
						y : 0
				}
		},

		initialize : function(element, url, options) {

				var self = this;

				this.parent(element);
				this.setOptions(options);
				this.url = url;
				this.empty = false;
																							
				this.autocomplete = new Element('div')
						.addClass('autocomplete')
						.addClass(this.options.uid)
						.inject(element, 'after');
						
				this.box.addClass(this.options.uid);		
				var l = new Element('div').addClass('autoloader').addClass('hide').inject(this.box);

				this.loader = new Loader({
						'onStart' : function() {
								l.removeClass('hide');
						},
						'onStop' : function() {
								l.addClass('hide');						
						}
				});

        // start the loader
				this.loader.start();
        
        var r = new Request.JSON({
            url: this.url,
            onComplete: function(json) {
                self.data = json;
                self.loader.stop();
            }
        }).get();
                
				this.addEvent('onRemove', this.reset.bind(this));						

				this.addEvent('onAdd', function(tag) {
						if(this.tags.length >= this.options.maxtags) this.stop = true;								
						this.reset();
				}.bind(this));	

				this.addEvent('onBeforeAdd', function() {				
						if(this.tags.length >= this.options.maxtags) dropdown.showError(this.options.maxalert);

            var value = this.value();
            if(value != '') this.input.value = value;

				}.bind(this));
												
			  window.addEvent('resize', this.resize.bind(this));
			  //window.addEvent('scroll', this.resize.bind(this));
        $('dropdown-content').addEvent('scroll', this.resize.bind(this));

				document.addEvent('click', function(e) {
						var t = e.target;

						// hide the autocomplete field
						if(!t.isParent(self.autocomplete)) {
								self.reset();						
								self.input.set('value', '');
						}	

				});						
												
				this.input.addEvent('keyup', function(event) {
								
            switch(event.key) {
                case "down":
                    this.down();
                    break;
                case "up":
                    this.up();
                    break;								
                case "backspace":
                    this.reset();		
                    this.load(this.input.value);				
                    break;
                case "esc":
                    this.reset();
                    break;
                default: 
                    this.load(this.input.value);														
                    break;
            }
								
		    }.bind(this));

				this.addEvent('onSelect', this.reset.bind(this));

		},
		
		json : function(url) {
		    console.log(url);
		},
		
		reset : function() {
				this.autocomplete.empty();
				this.empty = false;
		},
		value : function() {
				return (this.autocomplete.getElement('.selected')) ? this.autocomplete.getElement('.selected').get('text').clean() : '';
		},
		resize : function() {
								
				this.size 	= this.box.getSize();
				this.width  = this.size.x;
																
				this.autocomplete.setStyles({
						'width' : this.width-2
				});
		
		},
		load : function(search) {

				var that = this;
				var ul = new Element('ul');
				var counter = 0;
				this.resize();
											
				if(that.tags.length >= that.options.maxtags || search.clean() == '' || this.empty == true) return false;
		
				var data = {
						'format' : 'json',
						'limit'  : that.options.maxresults,
						'search' : search
				};
								
				this.data.each(function(tag) {
				    				 
				    if(counter == 5) return false;				 
				    				    				    
		        tag = tag.clean().toLowerCase();
            if(!tag.test('^' + search, 'i')) return false;
            
            if(tag.length < 0 || that.tags.contains(tag)) return false;

            li = new Element('li')
                .set('html', '<span>' + tag + '</span>')
                .addEvents({
                    'click' : that.add.bind(that, tag),
                    'mouseover' : function() {
                        this.addClass('over')
                    },
                    'mouseout' : function() {
                        this.removeClass('over');
                    }
                })
                .inject(ul);
                
            if(counter==0) li.addClass('first');
            counter++;
            				    
				});
				
        that.autocomplete.empty();
                        
        if(counter > 0) ul.inject(that.autocomplete);				
        else that.empty = true;
																									
		},
		down : function() {
				var selected = this.autocomplete.getElement('.selected');
		
				if(!selected) return this.firstAuto();
				if(selected == this.autocomplete.getElements('li').getLast()) return false;

				selected.removeClass('selected');
				selected.getNext().addClass('selected');
		},
		up : function() {
				
				var selected = this.autocomplete.getElement('.selected');
		
				if(!selected) return this.firstAuto();
				if(selected != this.autocomplete.getElement('li')) {
						selected.removeClass('selected');
						selected.getPrevious().addClass('selected');
				} else {
						selected.removeClass('selected');
						this.input.focus();
				}
				
		},
		firstAuto : function() {
				var first = this.autocomplete.getElement('li');
				if(!first) return false;
				this.autocomplete.getElements('.selected').removeClass('selected');
				first.addClass('selected');
		}
				
});






/* share stuff */
var share = {

		setupMailbox : function() {

				// initialize the contactbox
				this.mailbox = new ZooAutocomplete('dropdown-email-box', '/api/friends/', {
						'uid' : 'contacts',
						'maxalert' : 'You can\'t send this to more than 10 Friends!',
						'maxtags' : 10,
						'maxresults' : 5
				});
		
				this.mailbox.focus();

		},
				
		twitterCounter : function(field, limit) {
				if(!limit) limit = 140;
          
        var c     = $('twitter-counter');
				var text  = field.value;
				var count = text.length;
							
				c.removeClass('limit');			
				if(count > limit) c.addClass('limit');			
				c.set('text', limit - count); 
				
		},

		twitterSettings : function() {
				$('twitter-settings').toggleClass('hide');		
		}

};

