var ValidatedForm = Class.create({

	initialize: function(element) {
		this.form = $(element);
		this.fields	= [];
		this.form.select('input, textarea').each(function(inputElement) {
			var validators = this.getValidators(inputElement);
			if (validators.length > 0) {
				var field = new ValidatedField(inputElement, validators);
				this.fields.push(field);
				validators.each(function(validator) {
					field.field.observe('blur', function(event) {
						if (!field.validate(true)) {
							event.stop();
						}
					});
				}, this);
			}
		}, this);
		this.form.down('input[type="submit"]').observe('click', function(event) {
		  if (!this.validateAll(true)) {
		    event.stop();
		  }
		}.bind(this));
	},
	
	getValidators: function(element) {
		var validators = [];
		if (Element.hasClassName(element, 'validates-presence')) {
			validators.push(new PresenceFieldValidator(element.id));
		}
		if (Element.hasClassName(element, 'validates-email')) {
			validators.push(new EmailFieldValidator(element.id));
		}
		if (Element.hasClassName(element, 'validates-url')) {
			validators.push(new UrlFieldValidator(element.id));
		}
		return validators;
	},
	
	validateAll: function(toggleErrorMessage) {
		var result = true;
		this.fields.each(function(field){
			result &= field.validate(toggleErrorMessage);
		});
		return result;
	}

});

var ValidatedField = Class.create({
		
	initialize: function(element, validators) {
		this.field = $(element);
		this.validators = validators;
	},

	validate: function(toggleMessage) {
		var result = true;
		this.validators.each(function(validator) {
			if (!validator.validate(toggleMessage)) {
				result = false;
				throw $break;
			}
		});
		return result;
	}
	
});
	
var FieldValidator = Class.create({
	
	initialize: function(fieldId) {
		this.fieldId = fieldId;
	},
	
	toggleErrorMessage: function(isValid) {
		if (isValid) {
			Effect.Fade(this.getMessageId(), { duration: .2 });
		} else {
			Effect.Appear(this.getMessageId(), { duration: .2 });
		}
	},
	
	validate: function(isValid, toggleMessage) {
	  if (toggleMessage) {
	    this.toggleErrorMessage(isValid);
	  }
		return isValid;
	}
	
});

var EmailFieldValidator = Class.create(FieldValidator, {
	
	getMessageId: function() {
		return 'email-error-' + this.fieldId;
	},
	
	validate: function($super, toggleMessage) {
		return $super(
			$F(this.fieldId).strip().empty() || /^([a-zA-Z0-9\-\._]+)@(([a-zA-Z0-9\-_]+\.)+)([a-z]{2,3})$/.test($F(this.fieldId)),
			toggleMessage
		);
	}
	
});
	
var PresenceFieldValidator = Class.create(FieldValidator, {
	
	getMessageId: function() {
		return 'presence-error-' + this.fieldId;
	},
	
	validate: function($super, toggleMessage) {
		return $super(
			$F(this.fieldId) !== '',
			toggleMessage
		);
	}
	
});

var UrlFieldValidator = Class.create(FieldValidator, {
	
	getMessageId: function() {
		return 'url-error-' + this.fieldId;
	},
	
	validate: function($super, toggleMessage) {
		return $super(
			$F(this.fieldId).strip().empty() || /^(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/.test($F(this.fieldId)),
			toggleMessage
		);
	}
	
});

var Glider = Class.create({

  initialize: function(container, options, callback) {
    this.container = $(container);
    this.callback = callback;
    this.options = $H({ direction: 'x', transition: Effect.Transitions.sinoidal, duration: .6 }).merge(options);
    this.sectionsContainer = this.container.down('.sections');
    this.sectionInfo = this.collectSectionInfo();
    this.container.setStyle({
      height: this.sectionInfo.first().section.getHeight() + 'px',
      width: this.sectionInfo.first().section.getWidth() + 'px'
    });
    this.setInitialSection();
  },
  
  collectSectionInfo: function() {
    counter = -1;
    sections = this.sectionsContainer.select('.section');
    return sections.map(function(section) {
      counter++;
      return {
        section: $(section),
        index: counter,
        left: function() {
          value = 0;
          for (i = 0; i < counter; i++) {
            value += sections[i].getWidth();
          }
          return value;
        }(),
        top: function() {
          value = 0;
          for (i = 0; i < counter; i++) {
            value += sections[i].getHeight();
          }
          return value;
        }()
      }
    });
  },

  setInitialSection: function() {
    initial = null;
    if (document.location.href.indexOf('#') > 0) {
      initial = this.sectionInfo.find(function(sectionInfo) {
        return sectionInfo.section.id == document.location.href.split('#').last();
      });
      initial = initial ? initial.section : null;
    }
    if (!initial && (initialSection = this.sectionsContainer.select('.initial')).length == 1) {
      initial = initialSection[0];
    }
    if (!initial) {
      initial = this.sectionInfo.first().section;
    }
    this.show(initial.id, 0.0000000000001);
  },

  getSectionInfo: function(id) {
    return this.sectionInfo.find(function(sectionInfo) {
      return sectionInfo.section.id == id;
    });
  },

  calculateEffects: function(sectionInfo, duration) {
    effects = [];
    movements = { x: 0, y: 0 }
    scales =    { x: false, y: false, factor: 1}
    if (this.options.get('direction') == 'x') {
      direction = (this.sectionsContainer.positionedOffset().left + sectionInfo.left) > 0 ? -1 : 1;
      movements.x   = (Math.abs(this.sectionsContainer.positionedOffset().left + sectionInfo.left) * direction)
      scales.factor = sectionInfo.section.getWidth() / this.container.getWidth();
      scales.x      = true;
    } else {
      direction = (this.sectionsContainer.positionedOffset().top + sectionInfo.top) > 0 ? -1 : 1;
      movements.y   = (Math.abs(this.sectionsContainer.positionedOffset().top + sectionInfo.top) * direction)
      scales.factor = sectionInfo.section.getHeight() / this.container.getHeight();
      scales.y      = true;
    }
    effects.push(new Effect.Move(this.sectionsContainer, {
      duration: duration,
      x: movements.x,
      y: movements.y,
      transition: this.options.get('transition'),
      queue: { scope: 'simplabs:glider' }
    }));
    if (scales.factor != 1) {
      effects.push(new Effect.Scale(this.container, scales.factor * 100, {
        duration: duration,
        scaleX: scales.x,
        scaleY: scales.y,
        scaleContent: false,
        queue: { scope: 'simplabs:glider' }
      }));
    }
    return effects;
  },

  show: function(sectionId, duration) {
    duration = duration || this.options.get('duration');
    Effect.Queues.get('simplabs:glider').each(function(effect) { effect.cancel(); });
    sectionInfo = this.getSectionInfo(sectionId);
    if (sectionInfo == undefined) {
      return;
    }
    effects = this.calculateEffects(sectionInfo, duration);
    new Effect.Parallel(effects, {
      duration: duration,
      queue: { scope: 'simplabs:glider' }
    });
    if (this.options.get('onSlide')) {
      this.options.get('onSlide')(sectionInfo.section);
    }
  }
  
});

var GliderLink = Class.create({

  initialize: function(link, glider) {
    this.link = $(link);
    this.glider = glider;
    this.link.observe('click', this.onclick.bindAsEventListener(this));
  },

  onclick: function(event) {
    Event.stop(event);
    this.glider.show(this.link.href.split('#').last());
  }

});

var Imprint = Class.create({

  initialize: function(container, link) {
    this.container = $(container);
    this.link = $(link);
    this.link.observe('click', this.toggle.bindAsEventListener(this));
    this.showing = false;
  },

  toggle: function() {
    effects = [];
    if (this.showing) {
      effects.push(new Effect.BlindUp(this.container));
      effects.push(new Effect.Fade(this.container));
      this.showing = false;
    } else {
      effects.push(new Effect.BlindDown(this.container));
      effects.push(new Effect.Appear(this.container));
      this.showing = true;
    }
    new Effect.Parallel(effects, { duration: .7 })
  }

});

var ContactForm = Class.create({

  initialize: function(element) {
    this.form = $(element);
    this.successMessage = this.form.down('.successMessage');
    this.form.observe('submit', function(event) {
      event.stop();
		  new Ajax.Request(
		    this.form.action,
		    {
		      asynchronous: true,
		      parameters: this.form.serialize(),
		      onSuccess: function(transport) {
	          new Effect.SlideDown(this.successMessage, { duration: .7 });
	          new Effect.SlideUp(this.successMessage, { delay: 2.5, duration: .7 });
          }.bind(this)
		    }
		  );
		}.bind(this));
  }
 
});

function setAvticeMenu(section) {
  $$('ul.menu a').each(function(link) {
    link.removeClassName('active');
  });
  $('menu-' + section.id).addClassName('active');
}

document.observe('dom:loaded', function() {
	$$('form.validated').each(function(form) {
		var validatedForm = new ValidatedForm(form.id);
	});
	$$('div.formError').each(function(errorMessage) {
		errorMessage.observe('click', function(event) {
		  Effect.Fade(Event.element(event), {duration: 0.3});
		})
	});
  
  var glider = new Glider($('mainContent'), { onSlide: setAvticeMenu, direction: 'y' });
  $$('a[href^="#"]').each(function(link) {
    link = new GliderLink(link, glider);
  });
  var imprint = new Imprint($('imprint'), $('imprintLink'));
  var contactForm = new ContactForm('contactForm');
});

