// boekkat: cuecat support for javascript
// copyright 2005 jared jennings. all rights reserved.
// licensed under a BSD-style license. See LICENSE.txt.

// The Interpreter performs limited interpretation of book-related barcodes
// into different formats: e.g. it can take an ISBN+5 barcode and turn it
// into a ten-digit ISBN, or take an ISBN barcode and turn it into a 13-digit
// ISBN13.

function Actor() {
		
	// the Interpreter object is interrogated to find all of the functions
	// whose names don't start with the underline character (_). Each function
	// found is an interpreting function.
	this.interpreter = new Interpreter();

	// The order in which to try the interpreting functions.
	// An array of strings which are names of methods of the Interpreter.
	// The interpreting functions which are hardest to satisfy should come
	// first unless you know what you are doing.
	this.order = [];
	
	this.handlers = {
		"noInterpreter": function(triple) { 
			throw new NoInterpretationError("No interpretation found for barcode: "+
				triple+". The barcode could be invalid."); },
		"noHandler": function(triple) { 
			throw new NoHandlerError("No handler found for barcode: "+triple); }
	};
}

Actor.prototype.onBarcode = function(triple) {
	var i;
	var anyInterpreted, interpreted, handled;
	
	anyInterpreted = false;
	handled = false;
	// try each possible interpretation in turn. if it works, try to find a
	// handler for that interpretation.
	for(i = 0; (i < this.order.length) && !handled; i++) {
		var handlerName = this.order[i];
		var interpretFunc = this.interpreter[handlerName];

		interpreted = false;
		if(interpretFunc) {
			// the interpreter can't return null to indicate failed interpretation
			// because null might be in the set of valid return values.
			try {
				value = interpretFunc.apply(this.interpreter, [triple]);
				interpreted = true;
				anyInterpreted = true;
			} catch(err) {
				if(!(err instanceof InterpreterFailure)) {
					// don't know what it is! throw it on up.
					throw err;
				}
			}
		}
		if(interpreted) {
			if(this.handlers[handlerName]) {
				// don't catch exception, we don't have anything good
				// to do about it here.
				this.handlers[handlerName](value);
				handled = true;
			}
		}
	}
	if(!handled) {
		if(anyInterpreted) {
			this.handlers.noHandler(triple);
		} else {
			this.handlers.noInterpreter(triple);
		}
	}
};

Actor.prototype.hookUp = function(boekkat) {
	boekkat.actor = this;
};			


// degenerate singleton Actors
nullActor = new Actor();
nullActor.onBarcode = function(triple) {};

alertActor = new Actor();
alertActor.onBarcode = function(triple) { alert(triple); }


function NoInterpretationError(text) {
	Error.apply(this, [text,text]);
	this.name = "NoInterpretationError";
}
NoInterpretationError.prototype = new Error;
NoInterpretationError.prototype.constructor = NoInterpretationError;

function NoHandlerError(text) {
	Error.apply(this, [text,text]);
	this.name = "NoHandlerError";
}
NoHandlerError.prototype = new Error;
NoHandlerError.prototype.constructor = NoHandlerError;


// Handler factories

function putInFieldAndSubmit(field) {
	return function(data) {
		field.value = data;
		field.form.submit();
	};
}

function putInField(field) {
	return function(data) {
		field.value = data;
	};
};

