/**********
     TITLE: Music Object Extension - Dynamic
   VERSION: 1.1.0
    AUTHOR: Chris van Rensburg
 COPYRIGHT: 1996-1999 Beatnik, Inc. All Rights Reserved
  REQUIRES: music-object.js (3.2.0 or higher)
**********/

function mo_kwiklistToArray (kwiklist) {
	var
		items = new Array (),
		optionStart = 0,
		lastCharPos = -1
	;
	items [0] = '';
	while (true) {
		var
			separatorPos = mo_indexOf (kwiklist,'|',lastCharPos + 1),
			openerPos = mo_indexOf (kwiklist,'[',lastCharPos + 1),
			charPos = Math.min (separatorPos,openerPos),
			suffix = kwiklist.substring (lastCharPos + 1,charPos)
		;
		for (var itemNo = optionStart; itemNo < items.length; itemNo++) items [itemNo] += suffix;
		if (charPos == kwiklist.length) {
			break;
		} else if (separatorPos == charPos) {
			items [items.length] = '';
			optionStart = items.length - 1;
		} else if (openerPos == charPos) {
			lastCharPos = charPos;
			var level = 1;
			while (level > 0) {
				openerPos = mo_indexOf (kwiklist,'[',charPos + 1);
				closerPos = mo_indexOf (kwiklist,']',charPos + 1);
				charPos = Math.min (openerPos,closerPos);
				level += (openerPos == charPos) ? 1 : -1;
			}
			var suffixes = mo_kwiklistToArray (kwiklist.substring (lastCharPos + 1,charPos));
			if (suffixes.length == 1) {
				suffixes [1] = suffixes [0];
				suffixes [0] = '';
			}
			for (var itemNo = items.length - 1; itemNo >= optionStart; itemNo--) {
				for (var suffixNo = suffixes.length - 1; suffixNo >= 0; suffixNo--)
					items [optionStart + (itemNo - optionStart) * suffixes.length + suffixNo] = items [itemNo] + suffixes [suffixNo]
				;
			}
		}
		lastCharPos = charPos;
	}
	return items;
}

function mo_random (rangeLimitA,rangeLimitB) {
	if (typeof (rangeLimitB) == 'undefined') {
		return Math.round (Math.random () * (rangeLimitA - 1)) + 1;
	} else if (rangeLimitB == null) {
		return rangeLimitA;
	} else {
		return rangeLimitA + Math.round (Math.random () * (rangeLimitB - rangeLimitA));
	}
}

function mo_Shuffler_reset () {
	for (var flagNo = 0; flagNo < this.items.length; flagNo++) this.flags [flagNo] = false;
	this.flagsSelected = 0;
}

function mo_Shuffler_next () {
	with (this) {
		var
			flagsFound = 0,
			randomFlag = mo_random (items.length - flagsSelected)
		;
		for (var flagNo = 0; flagNo < items.length; flagNo++) {
			if (!this.flags [flagNo]) {
				flagsFound++;
				if (flagsFound == randomFlag) {
					flags [flagNo] = true;
					break;
				}
			}
		}
		flagsSelected++;
		if (flagsSelected == items.length) reset ();
		return items [flagNo];
	}
}

function mo_Shuffler () {
	/*** Instance State Variables ***/
	var args = mo_Shuffler.arguments;
	if (args.length == 1 && typeof (args [0]) == 'object') {
		this.items = args [0];
	} else {
		this.items = new Array ();
		if (args.length == 1 && typeof (args [0]) == 'number') {
			for (var itemNo = 0; itemNo < args [0]; itemNo++) this.items [itemNo] = itemNo + 1;
		} else {
			for (var itemNo = 0; itemNo < args.length; itemNo++) this.items [itemNo] = args [itemNo];
		}
	}
	this.flags = new Array ();

	/*** Exposed Methods ***/
	this.next = mo_Shuffler_next;
	this.reset = mo_Shuffler_reset;

	/*** Initialization ***/
	this.reset ();
}

function mo_randomFromList () {
	var args = mo_randomFromList.arguments;
	if (args.length == 1 && typeof (args [0]) == 'object') args = args [0];
	return (args.length == 0) ? '' : args [mo_random (args.length) - 1];
}

function mo_playRandomNote (channelNo,bankNo,programNo,noteMin,noteMax,velocityMin,velocityMax,durationMin,durationMax,volumeMin,volumeMax,panA,panB) {
	with (this) {
		if (typeof (volumeMin) == 'integer') setController (channelNo,7,mo_random (volumeMin,volumeMax));
		if (typeof (panB) == 'integer') setController (channelNo,10,mo_random (panA,panB));
		playNote (
			channelNo,
			bankNo,
			programNo,
			mo_random (Music.getNoteNumber (noteMin),Music.getNoteNumber (noteMax)),
			mo_random (velocityMin,velocityMax),
			mo_random (durationMin,durationMax)
		);
	}
}

function mo_extractGroup (sourceArray,groupPrefix) {
	var
		includeAll = typeof (groupPrefix) == 'undefined' || groupPrefix == null || groupPrefix == '' || groupPrefix.indexOf ('[all') == 0,
		result = new Array ()
	;
	for (var itemNo = 0; itemNo < sourceArray.length; itemNo++) {
		if (includeAll || sourceArray [itemNo].indexOf (groupPrefix) == 0)
			result [result.length] = sourceArray [itemNo]
		;
	}
	return result;
}

function mo_randomFromGroup (sourceArray,groupPrefix) {
	var subGroup = mo_extractGroup (sourceArray,groupPrefix);
	return (subGroup.length == 0) ? '' : subGroup [mo_random (subGroup.length) - 1];
}

function mo_groovoidGroup (groupPrefix) {return mo_extractGroup (Music.groovoids,groupPrefix)}
function mo_randomGroovoid (groupPrefix) {return mo_randomFromGroup (Music.groovoids,groupPrefix)}

/*** Static Properties ***/

Music.groovoids = mo_kwiklistToArray ('UI-[BeepClick1|Chimes|Choice1|Click[1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18]|CarriageReturn|FunnyBeep|Load1|MouseOver[1|2|Drone1]|Notification[1|2|3]|OpenOrClose[1|2|3]|Question|SimpleClick[1|2]|SystemBeep|TeletypeBurst2|TypeOneKey]|Hits-[BlastOff|Kicker[1|2|5]|LudwigVan|Magic|MysteryChime|SportsOrganCharge|ZoomAndHit]|Fanfare-[Arrival|Cascade|CorpSting1|Finished|Horserace|Mars|Majesty|Presenting|Sports]|Background-[Beeps|Clock|Dubby|Funky|Groove2|InfoPulse|Latin|News|Piano|SimpleTyping|Smooth|StillWaiting|Teletype]|Misc-[CashRegister|ThruPhoneRing]');

/*** Instance Methods ***/

mo_addInstanceMethods ('playRandomNote');

/*** Static Methods ***/

mo_addStaticMethods ('extractGroup','groovoidGroup','kwiklistToArray','random','randomFromGroup','randomFromList','randomGroovoid','Shuffler');

