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

// This is the CueCat object. It takes the string of numbers, letters and dots
// from an un-declawed CueCat, and decodes it into the serial number of the
// CueCat, the type of barcode, and the contents of the barcode.

// usage:
// // catch CueCat input somehow in cuecat_input
// arr_of_decoded = CueCat.decodeAll(cuecat_input);
// // now arr_of_decoded is an Array of Strings containing 
// // [0] the serial number of the CueCat
// // [1] the type of barcode scanned, in the CueCat three-letter parlance
// // [2] the contents of the barcode.

// ported from cue.py - see http://www.logorrhea.com/cuecat/mirrors.dat
// can handle letters in barcodes, unlike the cuecat_decode.js available from
// the same places as cue.py.

var CueCat = new Object();

	CueCat.uustring = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-";
	CueCat.uuestring= "dcbahgfelkjiponmtsrqxwvuBAzyFEDCJIHGNMLKRQPOVUTSZYXW32107654-+98";

	CueCat.uudecode = function(uuinput) {
		var numbers = new Array();
		var padding = 0;
		var i;
		var r = "";
		var n;
		for(i=0; i < uuinput.length; i++) {
			numbers[numbers.length] = (CueCat.uustring.indexOf(uuinput.charAt(i)));
		}
		
		if(numbers.length % 4 == 1) {
			// illegal.
			return "";
		} else {
			// pad out to an even multiple of 4.
			while(numbers.length % 4 != 0) {
				numbers[numbers.length] = 0;
				padding++;
			}
		}

		while(numbers.length > 0) {
			// deal with the first four...
			n = ((numbers[0] << 6 | numbers[1]) << 6 | numbers[2]) << 6 | numbers[3];

			r = r + String.fromCharCode((n >> 16) ^ 67) + String.fromCharCode((n >> 8 & 255) ^ 67) + String.fromCharCode((n & 255) ^ 67);
			
			// and then slice them off.
			numbers = numbers.slice(4);
		}
		if(padding != 0) {
			// padding == 1: we added six bits of padding.
			// out of the twenty-four last bits, eighteen are data.
			// 18 > 16, so out of the three output bytes, two are data. chop off one
			// padding == 2: we added twelve bits of padding.
			// out of the twenty-four last bits, twelve are data.
			// 16 > 12 > 8, so out of the three output bytes, one is data. chop off two
			return r.slice(0,r.length-padding);
		} else {
			return r;
		}
	};

	CueCat.uuencode = function(input) {
		var numbers = new Array();
		var padding = 0;
		var i;
		var r = "";
		var n;

		for(i=0; i < input.length; i++) {
			numbers[numbers.length] = input.charCodeAt(i) ^ 67;
		}
		while(numbers.length % 3 != 0) {
			numbers[numbers.length] = 32;
		}
		
		while(numbers.length > 0) {
			// deal with the first three...
			// twenty-four bits long
			n = ((numbers[0] << 8) | numbers[1]) << 8 | numbers[2];
			r = r + // string concatenation!
				CueCat.uustring[(n >> 18) & 0x3f] + 
				CueCat.uustring[(n >> 12) & 0x3f] +
				CueCat.uustring[(n >>  6) & 0x3f] + 
				CueCat.uustring[n         & 0x3f];
			numbers = numbers.slice(3);
		}
		return r;
	};

	CueCat.decodeAll = function(catstring) {
		var parts = catstring.substr(1,catstring.length-2).split(".");
		var result = new Array(parts.length);
		var i;
		for(i=0; i < parts.length; i++) {	
			result[i] = CueCat.uudecode(parts[i]);
		}
		return result;
	};
