// Released under the GNU GPLv3. Copyright 2010 Samuel Williams.

function AggregateCallback (timeout, enforce, callback) {
    this.timeout = timeout;
    this.enforce = enforce;

    this.callback = callback;

    this.timer = null;
    this.fired = null;
}

AggregateCallback.prototype.fire = function () {
    this.fired = new Date();
    this.callback();
}

AggregateCallback.prototype._expired = function () {
    // Returns true if we have been fired further than maxTimeout in the past.
    return !this.fired || ((new Date() - this.fired) > this.timeout);
}

AggregateCallback.prototype.update = function () {
    if (this._expired() && this.enforce)
        this.fire()

    if (this.timer) {
        clearTimeout(this.timer);
        this.timer = null;
    }

    var target = this;
    this.timer = setTimeout(function () { target.fire(); }, this.timeout);
}

jQuery(function($) {
	var form = $('#paste_form');
	var text = $('textarea[name=body]', form);
	var brush = $('input[name=brush]', form);
	var body = $('textarea[name=body]', form)
	var preview = $('#preview');
	
	function updatePreview () {
		preview.empty();
		
		if (body.val() == '')
			return;
		
		var pre = $('<pre></pre>');
		pre.text(body.val()).syntax({
				replace: false,
				brush: Syntax.aliases[brush.val()],
				layout: Syntax.defaultOptions.blockLayout,
				theme: "base"
			}, 
			function (options, html, container) {
				html.appendTo(preview);
			}
		);
	}
	
	var aliases = [];
	for (var name in Syntax.aliases)
		aliases.push(name);
	
	brush.autocomplete({
		source: aliases,
		change: updatePreview
	})
	
	var callback = new AggregateCallback(1000, false, function() {
		updatePreview();
	});
	
	body.keyup(function() {
		callback.update();
	});
	
	$.validator.addMethod("validBrush", function(value) {
		return aliases.indexOf(value.toLowerCase()) != -1;
	}, "Please specify a valid language.");
	
	form.validate({
		rules: {
			brush: "validBrush",
			body: "required"
		},
		messages: {
			body: "Please enter some text."
		},
		errorPlacement: function (error, element) { 
			$(element).parent("dd").prev("dt").append(error);
		}
	});
});

