/** @preserve
jSignature v2 jSignature's custom "base30" format export and import plugins.

*/
/**
Copyright (c) 2011 Willow Systems Corp http://willow-systems.com
MIT License <http://www.opensource.org/licenses/mit-license.php>
*/

;(function(){

	var chunkSeparator = '_' 
	, charmap = {} // {'1':'g','2':'h','3':'i','4':'j','5':'k','6':'l','7':'m','8':'n','9':'o','a':'p','b':'q','c':'r','d':'s','e':'t','f':'u','0':'v'}
	, charmap_reverse = {} // will be filled by 'uncompress*" function
	// need to split below for IE7 (possibly others), which does not understand string[position] it seems (returns undefined)
	, allchars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX'.split('') 
	, bitness = allchars.length / 2
	, minus = 'Z'
	, plus = 'Y'
	
	for(var i = bitness-1; i > -1; i--){
		charmap[allchars[i]] = allchars[i+bitness]
		charmap_reverse[allchars[i+bitness]] = allchars[i]
	} 
	var remapTailChars = function(number){
		// for any given number as string, returning string with trailing chars remapped something like so:
		// '345' -> '3de'
		var chars = number.split('') 
		, l = chars.length
		// we are skipping first char. standard hex number char = delimiter
		for (var i = 1; i < l; i++ ){
			chars[i] = charmap[chars[i]]
		}
		return chars.join('')
	}
	, compressstrokeleg = function(data){
		// we convert half-stroke (only 'x' series or only 'y' series of numbers)
		// data is like this:
		// [517,516,514,513,513,513,514,516,519,524,529,537,541,543,544,544,539,536]
		// that is converted into this:
		// "5agm12100p1235584210m53"
		// each number in the chain is converted such:
		// - find diff from previous number
		// - first significant digit is kept as digit char. digit char = start of new number.
		// - consecutive numbers are mapped to letters, where 1 to 9 are A to I, 0 is O
		// Sign changes are denoted by "P" - plus, "M" for minus.
		var answer = []
		, lastwhole = 0
		, last = 0
		, lastpolarity = 1
		, l = data.length
		, nwhole, n, absn
		
		for(var i = 0; i < l; i++){
			// we start with whole coordinates for each point
			// coords are converted into series of vectors:
			// [512, 514, 520]
			// [512, +2, +6]
			nwhole = Math.round(data[i])
			n = nwhole - lastwhole			
			lastwhole = nwhole

			// inserting sign change when needed.
			if (n < 0 && lastpolarity > 0) {
				lastpolarity = -1
				answer.push(minus)
			}
			else if (n > 0 && lastpolarity < 0) {
				lastpolarity = 1
				answer.push(plus)
			}
			
			// since we have dealt with sign. let's absolute the value.
			absn = Math.abs(n)
			// adding number to list  We convert these to Hex before storing on the string.
			if (absn >= bitness) {
				answer.push(remapTailChars(absn.toString(bitness)))
			} else {
				answer.push(absn.toString(bitness))
			}
		}
		return answer.join('')
	}
	, uncompressstrokeleg = function(datastring){
		// we convert half-stroke (only 'x' series or only 'y' series of numbers)
		// datastring like this:
		// "5agm12100p1235584210m53"
		// is converted into this:
		// [517,516,514,513,513,513,514,516,519,524,529,537,541,543,544,544,539,536]
		// each number in the chain is converted such:
		// - digit char = start of new whole number. Alpha chars except "p","m" are numbers in hiding.
		//   These consecutive digist expressed as alphas mapped back to digit char.
		//   resurrected number is the diff between this point and prior coord.
		// - running polaritiy is attached to the number.
		// - we undiff (signed number + prior coord) the number.
		// - if char 'm','p', flip running polarity 
		var answer = []
		, chars = datastring.split('')
		, l = chars.length
		, ch
		, polarity = 1
		, partial = []
		, preprewhole = 0
		, prewhole
		for(var i = 0; i < l; i++){
			ch = chars[i]
			if (ch in charmap || ch === minus || ch === plus){
				// this is new number - start of a new whole number.
				// before we can deal with it, we need to flush out what we already 
				// parsed out from string, but keep in limbo, waiting for this sign
				// that prior number is done.
				// we deal with 3 numbers here:
				// 1. start of this number - a diff from previous number to 
				//    whole, new number, which we cannot do anything with cause
				//    we don't know its ending yet.
				// 2. number that we now realize have just finished parsing = prewhole
				// 3. number we keep around that came before prewhole = preprewhole

				if (partial.length !== 0) {
					// yep, we have some number parts in there.
					prewhole = parseInt( partial.join(''), bitness) * polarity + preprewhole
					answer.push( prewhole )
					preprewhole = prewhole
				}

				if (ch === minus){
					polarity = -1
					partial = []
				} else if (ch === plus){
					polarity = 1
					partial = []
				} else {
					// now, let's start collecting parts for the new number:
					partial = [ch]					
				}
			} else /* alphas replacing digits */ {
				// more parts for the new number
				partial.push(charmap_reverse[ch])
			}
		}
		// we always will have something stuck in partial
		// because we don't have closing delimiter
		answer.push( parseInt( partial.join(''), bitness ) * polarity + preprewhole )
		
		return answer
	}
	, compressstrokes = function(data){
		var answer = []
		, l = data.length
		, stroke
		for(var i = 0; i < l; i++){
			stroke = data[i] 
			answer.push(compressstrokeleg(stroke.x))
			answer.push(compressstrokeleg(stroke.y))
		}
		return answer.join(chunkSeparator)
	}
	, uncompressstrokes = function(datastring){
		var data = []
		, chunks = datastring.split(chunkSeparator)
		, l = chunks.length / 2
		for (var i = 0; i < l; i++){
			data.push({
				'x':uncompressstrokeleg(chunks[i*2])
				, 'y':uncompressstrokeleg(chunks[i*2+1])
			})
		}
		return data
	}
	, acceptedformat = 'image/jsignature;base30'
	, pluginCompressor = function(data){
		return [acceptedformat , compressstrokes(data)]
	}
	, pluginDecompressor = function(data, formattype, importcallable){
		if (typeof data !== 'string') return
		if (data.substring(0, acceptedformat.length).toLowerCase() === acceptedformat) {
			data = data.substring(acceptedformat.length + 1) // chopping off "," there
		}
		importcallable( uncompressstrokes(data) )
	}
	, Initializer = function($){
		var mothership = $.fn['jSignature']
		mothership(
			'addPlugin'
			,'export'
			,'base30' // alias
			,pluginCompressor
		)
		mothership(
			'addPlugin'
			,'export'
			,acceptedformat // full name
			,pluginCompressor
		)
		mothership(
			'addPlugin'
			,'import'
			,'base30' // alias
			,pluginDecompressor
		)
		mothership(
			'addPlugin'
			,'import'
			,acceptedformat // full name
			,pluginDecompressor
		)
	}
	

//  //Because plugins are minified together with jSignature, multiple defines per (minified) file blow up and dont make sense
//	//Need to revisit this later.
	
//	if ( typeof define === "function" && define.amd != null) {
//		// AMD-loader compatible resource declaration
//		// you need to call this one with jQuery as argument.
//		define(function(){return Initializer} )
//	} else {
		// global-polluting outcome.
		if(this.jQuery == null) {throw new Error("We need jQuery for some of the functionality. jQuery is not detected. Failing to initialize...")}
		Initializer(this.jQuery)
//	}

	if (this.jSignatureDebug) {
		this.jSignatureDebug['base30'] = {
			'remapTailChars':remapTailChars
			, 'compressstrokeleg':compressstrokeleg
			, 'uncompressstrokeleg':uncompressstrokeleg
			, 'compressstrokes':compressstrokes
			, 'uncompressstrokes':uncompressstrokes
			, 'charmap': charmap
		}
	}

}).call(typeof window !== 'undefined'? window : this);