var Validator = new Class({
  Implements: [Options, Events],
  options: {
    onApprovedSubmit: function(){}
  },
  initialize: function(elm, options) {
    this.setOptions(options);
    
    this.form = document.id(elm);
    this.errors = [];
    this.inputs = {};
      
    var rows = this.form.getElements('div.required');
    rows.each(function(row) {
          
      var inputs = row.getElements('input,select,textarea');
          
      inputs.each(function(input) {
        this.inputs[input.get('name')] = []; 
      }.bind(this));
          
      inputs.each(function(input) {
        this.inputs[input.get('name')].push(input);
      }.bind(this));
          
    }.bind(this));
      
    this.form.addEvent('submit', function(e) {
      return this.validate(e); 
    }.bind(this));
  },
  validate: function(e) { 

    Object.each(this.inputs, function(inputs, key) {
      inputs.each(function(input) {
        var tagName = input.get('tag').capitalize();
        var obj = Validator.Fields[tagName];
              
        if(!obj) return false;
              
        var field = new obj(input);
        if(!field.validate()) {                  
          Validator.Error.getInstance(input, field);
        }
      });
    });
      
    if(Validator.Error.getActive().length > 0) {
      e.stop();
      this.handleErrors();
      return;
    }
    
    this.fireEvent('approvedSubmit', e);
  },
  handleErrors: function() {
    var errors = Validator.Error.getActive();
    if(errors.length > 0) {
      errors.each(function(error) {
          error.reevaluate();
      });
      
      errors[0].input.focus();
    }
  }           
});

Validator.Error = new Class({
  initialize: function(input, validator) {
    this.input = document.id(input);
    this.validator = validator;
    this.visible = false;
    this.elm = null;
    Validator.Error.instances[this.input.get('name')] = this;
  },
  reevaluate: function() {
    if(!this.validator.validate()) {
      this.add();
      return false;
    }
        
    this.remove();
    return true;
  },
  add: function() {
    if(!this.visible) {
            
      this.elm = new Element('label', {
        html: 'Please enter a value',
        'for': this.input.get('id'),
        'class': 'error'
      });
      this.elm.inject(this.input, 'after');
            
      this.visible = true;

    }
        
  },
  remove: function() {
    if(!this.elm) return;
    this.elm.destroy();
    this.elm = null;
  }
});
Validator.Error.instances = {};
Validator.Error.getInstance = function(input, validator) {
  if(Object.keys(Validator.Error.instances).contains(input.name)) {
    return Validator.Error.instances[input.name];
  }
    
  return new Validator.Error(input, validator);
};
Validator.Error.getActive = function() {
  return Object.values(Validator.Error.instances).filter(function(item) {
    return !item.reevaluate();
  });
};

Validator.Fields = {};
Validator.Fields.Base = new Class({
  initialize: function(elm) {
    this.elm = $(elm);
  },
  validate: function() {
    return false;
  }
});

Validator.Fields.Input = new Class({
  Extends: Validator.Fields.Base,
  validate: function() {
    return this.elm.get('value') != '';
  }
});

Validator.Fields.Textarea = new Class({
  Extends: Validator.Fields.Input
});

Validator.Fields.Select = new Class({
  Extends: Validator.Fields.Input
});


var ImageUploader = new Class({
  Implements: Options,
  options: (function() {
    return {
      limit: 4
    }
  }()),
  initialize: function(button, container, options) {
    this.setOptions(options);
    this.button = $(button);
    this.container = $(container);
    this.files = [];
    this.button.addEvent('click', this.addInput.bindWithEvent(this));
  },
  addInput: function() {
    if(this.files.length >= this.options.limit) return false;
    
    var li = new Element('li');
    var input = new Element('input', {type: 'file', name: 'images[]'});
    this.files.push(new ImageUploader.File(input, li, this));
    
    input.inject(li);
    
    li.inject(this.container);
    input.focus();
    
    this.onUpdate();
    
  },
  removedImage: function(image) {
    this.files.erase(image);
    this.onUpdate();
  },
  onUpdate: function() {
    if(this.files.length >= this.options.limit) {
      this.button.addClass('images-full');
    } else {
      this.button.removeClass('images-full');
    }
  }
});

ImageUploader.File = new Class({
  initialize: function(input, li, parentClass) {
    this.input = $(input);
    this.li = $(li);
    this.parentClass = parentClass;
    this.input.addEvent('change', this.selected.bindWithEvent(this));
  },
  selected: function() {
    
    this.li.addClass('file-selected');
    
    var fileName = this.input.get('value').split(/[\/\\]/).getLast();
    
    var a = new Element('a', {href: '#', html: fileName});
    a.addEvent('click', this.clicked.bindWithEvent(this));
    a.inject(this.li);
  },
  clicked: function(e) {
    e.stop();
    this.li.destroy();
    this.parentClass.removedImage(this);
  }
});



var Placeholder = new Class({
  initialize: function(elm, text) {
    this.elm = $(elm);
    this.text = text;
    
    // Checks if the browser has support for HTML5 input placeholder
    
    if(!Browser.ie) { // fails in IE
      if(Object.keys(new Element('input')).contains('placeholder')) {
        this.elm.set('placeholder', text);
        return; // nothing left to do
      }  
    }
    
    this.elm.addEvent('focus', this.action.bindWithEvent(this, this.text, ''));
    
    var blur = function() { this.action(null, '', this.text); };
    this.elm.addEvent('blur', blur.bindWithEvent(this));
    
    blur.call(this);
  },
  action: function(e, match, replace) {
    if(this.elm.get('readonly')) return;
    if(this.elm.get('value') == match) {
      this.elm.set('value', replace);
    }
  }
});


var SelectAll = new Class({
  Implements: [Options, Events],
  options: {
    onAllChecked: function(button) {
      button.checked = true;
    },
    onSomeChecked: function(button) {
      button.checked = false;
    }
  },
  initialize: function(button, inputName, options) {
    this.setOptions(options);
    
    this.button = $(button);
    this.inputClass = inputName;
    
    this.inputs = $$('input[type=checkbox][class="'+ inputName+ '"]');
    this.inputs.addEvent('change', this.registerInputClick.bindWithEvent(this));
    this.button.addEvent('change', this.selectAllClick.bindWithEvent(this));
  },
  registerInputClick: function(e) {
    if(this.inputs.length == this.getAllCheckedElms().length) {
      this.fireEvent('allChecked', this.button, this.inputs);
    } else {
      this.fireEvent('someChecked', this.button, this.inputs);
    }
  },
  selectAllClick: function(e) {
    this.toggleInputs(e.target.checked);
  },
  toggleInputs: function(on) {
    var elms = this.getAllUncheckedElms();
    if(!on) {
      var elms = this.getAllCheckedElms();
    }
    
    elms.each(function(elm) { elm.checked = on; });
  },
  getAllCheckedElms: function() {
    return this.inputs.filter(function(elm) { return elm.checked; });
  },
  getAllUncheckedElms: function() {
    return this.inputs.filter(function(elm) { return !elm.checked; });
  }
});

var RatingStars = new Class({
  Implements: [Options,Events],
  options: {
    onSet: function() {}
  },
  initialize: function(elm, options) {
    this.setOptions(options);
    
    this.select = document.id(elm);
    this.values = this.select.getElements('option');
    
    this.stars = [];
    this.values.each(function(option) {
      if(!option.get('value')) return;
      this.stars.push(new RatingStars.Star(option.get('value')));
    }, this);
    
    this.select.setStyle('display', 'none');
    
    var ul = new Element('ul', {'class': 'rating-star-ul'});
    
    var lis = [];
    this.links = [];
    
    var star_count = this.stars.length;
    this.stars.each(function(star, index) {
      var li = new Element('li');
      var a = new Element('a', {href:'#', 'class': 'rating-star'});
      
      a.addEvents({
        mouseover: function() {
          for(var i = 0; i <= index; i++) {
            this.links[i].addClass('hover');
          }
          
          
          for(i = (index + 1); i < star_count; i++) {
            this.links[i].addClass('norm');
          }
        }.bind(this),
        
        mouseout: function() {
          for(var i = 0; i <= index; i++) {
            this.links[i].removeClass('hover');
          }
          
          for(var i = (index + 1); i < star_count; i++) {
            this.links[i].removeClass('norm');
          }
          
        }.bind(this),
        
        click: function(e) {
          e.stop();
          this.set(star.value);
        }.bind(this)
      });
      
      a.inject(li);
      this.links.push(a);
      
      
      lis.push(li);
    }.bind(this));
    
    lis.each(function(li) { li.inject(ul); });
    ul.inject(this.select, 'after');
    
    if(this.select.get('value')) {
      this.set(this.select.get('value'));
    }
  },
  set: function(value) {
    this.select.set('value', value);
  
    var index = this.stars.map(function(val) { 
      return val.value; 
    }).indexOf(value);
    
    this.links.each(function(elm) { elm.removeClass('set'); });
    
    for(var i = 0; i <= index; i++) {
      this.links[i].addClass('set');
    }
    
    this.fireEvent('set', value);
  }
});

RatingStars.Star = new Class({
  initialize: function(value) {
    this.value = value;
  }
});

var Slideshow = new Class({
  Implements: [Options, Events],
  options: {
    duration: 5000,
    slideClass: 'slideshow-slide'
  },
  initialize: function(elm, options) {
    this.setOptions(options);
    
    this.elm = $(elm);
    this.position = 0;
    this.playing = false;
    
    this.frames = this.elm.getElements('.' + this.options.slideClass);
    
    if(this.frames.length <= 1)
    {
      return;
    }
    
    this.frames.set('opacity', 0);
    
    this.frames.each(function(frame) {
      
      frame.set('tween', { onComplete: function() {
                
        var dataJson = frame.get('data-slide');
        var data = JSON.decode(dataJson);
        
        var duration = this.options.duration;
        
        if(data) {
          duration = (data.duration || this.options.duration);
        }
        
        this.frameFinished(duration);
      }.bind(this) });
    }.bind(this));
    
    
    this.start();
  },
  start: function() {
    this.playing = true;
    this.frames[this.position].tween('opacity', 1);
  },
  next: function() {
    this.stop();
    
    this.frames[this.position].tween('opacity', 0);
    
    this.position += 1;

    if(!this.frames[this.position]) {
      this.position = 0;
    }
    
    this.start();
  },
  back: function() {
    if(this.frames[this.position--]) {
      this.position = this.position.length;
    }
  },
  stop: function() {
    this.playing = false;
    $clear(this.timer);
  },
  frameFinished: function(duration) {
    $clear(this.timer);
    this.timer = setTimeout(this.next.bindWithEvent(this), 
        duration);
  }
});


var Gallery = new Class({
  Implements: [Options, Events],
  page: 0,
  options: {
    limit: 4
  },
  initialize: function(main, back, next, options) {
    this.setOptions(options);
    
    this.main = main;
    this.aBack = $(back);
    this.aNext = $(next);
    
    if(this.aNext.get('tag') == 'a') {
      this.aNext.addEvent('click', this.setUpLink.bindWithEvent(this, 'next'));
    }
    
    if(this.aBack.get('tag') == 'a') {
      this.aBack.addEvent('click', this.setUpLink.bindWithEvent(this, 'back'));
    }
    
    this.request = new Request({
      url: '/gallery_loader.php',
      method: 'get',
      onComplete: this.update.bindWithEvent(this)
    });
  },
  setUpLink: function(e, action) {
    
    e.stop();
    this[action]();
  },
  next: function() {
    this.page++;
    this.request.send('offset='+ (this.page * this.options.limit)+ '&limit='+ this.options.limit);
  },
  back: function() {
    this.page--;
    this.request.send('offset='+ (this.page * this.options.limit)+ '&limit='+ this.options.limit);
  },
  goTo: function(imageName) {
    this.request.send('imageName='+ imageName+ '&limit='+ this.options.limit);
  },
  update: function(res) {
         
    var tr = $$('#thumbs table tr')[0];
    tr.empty();
    
    var thumbs = JSON.decode(res);
    
    if(thumbs.has_next) {
      if($('next').get('tag') != 'a') {
        var parent = $('next').getParent();
        parent.empty();
        
        var a = new Element('a', {href: '#', id: 'next', html: 'Next'});
        a.inject(parent);
        a.addEvent('click', this.setUpLink.bindWithEvent(this, 'next'));
      }
    } else {
      if($('next').get('tag') == 'a') {
        var parent = $('next').getParent();
        parent.empty();
        
        var span = new Element('span', {id: 'next', html: 'Next'});
        span.inject(parent);
        
      }
    }
    
    if(thumbs.has_back) {
      if($('back').get('tag') != 'a') {
        var parent = $('back').getParent();
        parent.empty();
        
        var a = new Element('a', {href: '#', id: 'back', html: 'Back'});
        a.inject(parent);
        a.addEvent('click', this.setUpLink.bindWithEvent(this, 'back'));
      }
    } else {
      if($('back').get('tag') == 'a') {
        var parent = $('back').getParent();
        parent.empty();
        
        var span = new Element('span', {id: 'back', html: 'Back'});
        span.inject(parent);
        
      }
    }
    
    var images = [];
    
    thumbs.items.each(function(thumb) {
      var li = new Element('td');
      
      var a = new Element('a', {href: '/uploads/'+ thumb.file});
      a.inject(li);
      
      var i = $(new Image());
      images.push(i);
              
      i.set('src', '/uploads/t'+ thumb.file);
      i.inject(a);
      
      if(thumb.selected) {
        
        this.main.fireEvent('update', a.get('href'));
      }
      
      li.inject(tr);
      
      a.addEvent('click', function(e) {
        e.stop();
        
        $$('#thumbs td.selected').removeClass('selected');
        
        li.addClass('selected');
        
        this.main.fireEvent('update', a.get('href'));      
        
      }.bind(this));
      
    }.bind(this));      
    
  }
});





// Floatr


var Floatr = new Class({
	Implements: [Events, Options],
	options: {
    closeText: '[X]',
		effects: true,
    follow: false, // The content box will assume a fixed position on the screen 
                  //and move with the user as he/she scrolls or resizes.	
    onOpen: function() {}
	},
	initialize: function(options){
  
		this.setOptions(options);
    
		this.container = new Element('div', {id: 'floatr-wrapper'});
		this.modal = new Element('div', {id: 'floatr-modal', styles: {'z-index': '5400'}});
    this.boxFromTop = false;
		
		window.addEvents({
			//scroll: this.refactorSize.bindWithEvent(this),
			resize: this.refactorSize.bindWithEvent(this)
		});
		
		this.box = new Element('div', {id: 'floatr-box', styles: {width: '100px', height: '100px', 'z-index': '5500'}});
    this.box.addClass('shadow rounded-corners');
		this.info = new Element('div', {id: 'floatr-box-info'});
		
    this.loadedImage = false;
    
		this.closelink = new Element('a', {
			href: '#', 
			id: 'floatr-box-info-close'
		});
		
		this.content = new Element('div', {id: 'floatr-box-content'});
    
    this.fx = {
      modal: new Fx.Tween(this.modal, { duration: 150 }),
      box: new Fx.Morph(this.box, {duration: 600, transistion:  Fx.Transitions.Elastic.easeOut })
    };
		
		if(this.options.effects)
		{
			this.modalFx = new Fx.Tween(this.modal, {
				duration: 150
			});
      
      
		}
		
	},
	refactorSize: function() {
		var scroll = window.getScroll();
		var dim = window.getCoordinates();
		
		/*this.modal.setStyles({
			top: scroll.y+'px',
			height: dim.height+'px'
		});*/
    
    if(this.loadedImage) {
      //this.adjustModalToImage(this.loadedImage);
    }
    
    if(this.options.follow)
    {
      this.adjustBox();
    }
	},
  adjustBox: function(){
    
    if(this.boxFromTop === false)
    {
      this.boxFromTop = this.box.getPosition().y;
    }
    
    var windowscroll = window.getScroll();
    this.box.setStyle('top', (this.boxFromTop + windowscroll.y)+'px');
  },
  buildBox: function() {
    
    if(this.options.effects)
		{
			this.modalFx.set('opacity', 0);
		}
		
    if(Browser.ie7) { // ie7 goodness
      
      
      this.modal.inject(this.container);       
      
      this.box.inject(this.container, "top");
      
    } else {
      this.modal.inject(this.container);       
      this.box.inject(this.container);
    }
    
		this.info.inject(this.box);
		this.closelink.inject(this.info);
		this.closelink.set('html', this.options.closeText);
		this.content.inject(this.box);
		this.container.inject(document.body, 'top');
		
    this.refactorSize();
    this.adjustBox();
    
		if(this.options.effects)
		{
			//this.modalFx.start('opacity', 0.5);
      this.fx.modal.start('opacity', 0.5);
		}
		
		this.modal.addEvent('click', function(){
			this.close();
		}.bind(this));
		this.closelink.addEvent('click', this.close.bindWithEvent(this));
    
    IE7zindexHack();
    
    if(Browser.ie7) {
      this.modal.setStyle('z-index', '5400');
      this.box.setStyle('z-index', '5500');
    }
    
  },
  resize: function(width, height) {
    
    this.box.setStyle('overflow', 'hidden');
    
    this.fx.box.start({
      width: width.toInt() + 'px', 
      height: height.toInt()+ 'px',
      'margin-left': -(width/2) + 'px'
    });
    
    
    this.content.setStyles({
      width: width.toInt() + 'px',
      height: height.toInt() + 'px'
    });
    

  },
  
  resizeBoxToImage: function(image) {
    
    var width = (image.width.toInt() + 20), 
      height = (image.height.toInt() + 20);
    
    this.loadedImage = image;
        
    this.fx.box.addEvent('complete', function() {
      
      this.content.setStyles({
        width: width.toInt()+ 'px',
        height: height.toInt()+ 'px'
      });
      
    }.bind(this));
    
    this.fx.box.start({
      width: width.toInt() + 'px', 
      height: height.toInt()+ 'px',
      'margin-left': -(width/2) + 'px'
    });
    
    //this.adjustModalToImage(image);
        
  },
  
  adjustModalToImage: function(image) {
    
    this.fx.modal.set('height', 
      window.getCoordinates().height + image.height.toInt() + 'px');
      
  },
  
	open: function(obj) {
		if(obj.event)
		{
			obj.event.stop();
		}
    
		var content = obj.content;
		
		this.buildBox();
					
    if(obj.ajax && obj.ajax.url != '')
    {
      var xhroptions = {
        method: 'get',
        url: ''
      };
      
      var xhr = new Request($merge(xhroptions, obj.ajax));
      xhr.addEvent('complete', function(res) {
        this.content.set('html', res);
      }.bind(this));
      xhr.send();
      
      
    } else {
      if(content instanceof Floatr.Image) {
        this.content.addClass('floatr-img');
        this.container.addClass('floatr-loading');
        
        this.box.setStyle('overflow', 'hidden');
        this.content.setStyle('overflow', 'hidden');
        
        var i = new Image();
                
        $(i).addEvent('load', function() {
          
          this.container.removeClass('floatr-loading');
          
          
          this.resizeBoxToImage(i);
          
        }.bind(this));
        
        i.src = content.src;
        
        i.inject(this.content);
        return;
        
      } else if($type(content) == 'string'){
        var str = content;
      } else if ($(content)) {
        var elm = $(content);
        var str = elm.get('html');
      }
      this.content.set('html', str);
    }
        
    this.fireEvent('open');
	},
	close: function(e) {
    this.loadedImage = false;
		if(e)
		{
			e.stop();
		}
		this.container.destroy();
	}
});

Floatr.Image = new Class({
  initialize: function(src) {
    this.src = src;
  }
});

function loadFloatr(elm) {
  var img = new Floatr.Image(elm);
  
  var floatr = new Floatr();
  floatr.open({content: img});
}

// End Floatr



function IE7zindexHack() {
  if(Browser.ie7) {
    var zindex = 5000;
    $$('div').each(function(elm) {
      if(['relative', 'absolute'].contains(elm.getStyle('position'))) {
        elm.setStyle('z-index', zindex--); 
      }
    });
      
  }
}

window.addEvent('domready', function() {  
  
  $$('a.floatr-image').addEvent('click', function(e) {
    e.stop();
        
    loadFloatr(this.get('href'));
    
  });
  
  $$('.code-select').addEvent('click', function() {
    this.focus();
    this.select();
  });
  
  $$('.select-all').each(function(elm) {
    new SelectAll(elm, elm.get('value'));
  });
  
  IE7zindexHack();
});


