//=============================================================================================================
// File:		ucbScales.js
// Purpose: 	Implements a ScaleList data structure class and ScaleSelector which is a dropdown
//				control to select a scale.
// Author:		JDH/1999-2002

// Method:		ScaleList
// Purpose:		Holds a list of scales.
// Arguments:	None
//
function ScaleList( )
{
	this.scales = [];
	this.AddScale( 'Ionian (major)', 	[ 2, 2, 1, 2, 2, 2, 1 ] );
	this.AddScale( 'Dorian', 			[ 2, 1, 2, 2, 2, 1, 2 ] );
	this.AddScale( 'Phrygian', 			[ 1, 2, 2, 2, 1, 2, 2 ] );
	this.AddScale( 'Lydian', 			[ 2, 2, 2, 1, 2, 2, 1 ] );
	this.AddScale( 'Mixolydian', 		[ 2, 2, 1, 2, 2, 1, 2 ] );
	this.AddScale( 'Aeolian', 			[ 2, 1, 2, 2, 1, 2, 2 ] );
	this.AddScale( 'Locrian', 			[ 1, 2, 2, 1, 2, 2, 2 ] );
	this.AddScale( 'Chromatic', 		[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] );
	this.AddScale( 'Adolfos Scale',		[ 1, 2, 2, 1, 1, 2, 2 ] );
	this.AddScale( 'Diminished',		[ 2, 1, 2, 1, 2, 1, 2, 1 ] );
	this.AddScale( 'Enigmatic',			[ 1, 3, 2, 2, 2, 1, 1 ] );
	this.AddScale( 'Harmonic Minor',	[ 2, 1, 2, 2, 1, 3, 1 ] );
	this.AddScale( 'Hungarian Minor',	[ 2, 1, 3, 1, 1, 3, 1 ] );
	this.AddScale( 'Melodic Minor',		[ 2, 1, 2, 2, 2, 2, 1 ] );
	this.AddScale( 'Neapolitan',		[ 1, 2, 2, 2, 2, 2, 1 ] );
	this.AddScale( 'Neapolitan Minor',	[ 1, 2, 2, 2, 1, 3, 1 ] );
	this.AddScale( 'Pentatonic',		[ 2, 2, 3, 2, 3 ] );
	this.AddScale( 'Pentatonic Minor',	[ 3, 2, 2, 3, 2 ] );
	this.AddScale( 'Ten Tone',			[ 1, 2, 1, 1, 1, 1, 2, 1, 1 ] );
	this.AddScale( 'Whole Tone',		[ 2, 2, 2, 2, 2, 2 ] );
}

// Method:		AddScale
// Purpose:		Adds a scale to the list (internal use only).
// Arguments:	scaleName - The name of the scale
//				scaleIntevals - The intervals of the scale
//
ScaleList.prototype.AddScale = function( scaleName, scaleIntervals )
{
	var newScaleIndex = this.scales.length;
	this.scales[ newScaleIndex ] = {};
	this.scales[ newScaleIndex ].name = scaleName;
	this.scales[ newScaleIndex ].intervals = scaleIntervals;
}

// Method:		GetCount
// Purpose:		Gets the number of scales in the list.
// Arguments:	None
//
ScaleList.prototype.GetCount = function( )
{
	return this.scales.length;
}

// Method:		GetScaleName
// Purpose:		Gets the name of the scale at the specified index.
// Arguments:	scaleIndex - The scale index
//
ScaleList.prototype.GetScaleName = function( scaleIndex )
{
	return this.scales[ scaleIndex ].name;
}

// Method:		GetScaleIntervals
// Purpose:		Gets the intervals of the scale at the specified index.
// Arguments:	scaleIndex - The scale index
//
ScaleList.prototype.GetScaleIntervals = function( scaleIndex )
{
	return this.scales[ scaleIndex ].intervals;
}

// Method:		ScaleSelector
// Purpose:		Builds a scale selector object.
// Arguments:	thisObjectName - The name of this object.  Required because
//					this object will build HTML that will point back to itself.
//
function ScaleSelector( thisObjectName )
{
	// Store it's object name
	this.thisObjectName = thisObjectName;

	// Create a list of scales
	this.scales = new ScaleList();
	
	// Set the current scale to the first scale item
	this.currentScale = 0;
	
	// Set the observer object to null.  The observer is another object
	// that watches for changes in this object.
	this.observerObject = null;
}

// Method:		GetNotes
// Purpose:		Returns the note intervals of the currently selected scale.
// Arguments:	None.
//
ScaleSelector.prototype.GetNotes = function( )
{
	return this.scales.GetScaleIntervals( this.currentScale );
}

// Method:		onNewSelection
// Purpose:		Called by the <SELECT> tag when a new item is chosen.
// Arguments:	None
//
ScaleSelector.prototype.onNewSelection = function( newValue )
{
	// Set our new value
	this.currentScale = parseInt( newValue );
	
	// Notify the observer  (if this bombs it's because you haven't
	// called SetObserver.)
	this.observerObject.SetScaleNotes( this.GetNotes() );
}

// Method:		BuildSelector
// Purpose:		Builds the <SELECT> and <OPTION> tags and adds them to the document.
// Arguments:	None
//
ScaleSelector.prototype.BuildSelector = function( )
{
	s = "<SELECT SIZE=1 name=\"Scale\" ";
	s = s + "onchange = \"" + this.thisObjectName + ".onNewSelection( this.options[ this.selectedIndex ].value );\"";
	s = s + ">";
	var scaleCount = this.scales.GetCount();
	for( var scale = 0; scale < scaleCount; scale++ )
	{
		s = s + "<OPTION VALUE=\"" + scale + "\" >" + this.scales.GetScaleName( scale );
	}
	s = s + "</SELECT>";
	document.write( s );
}

// Method:		SetObserver
// Purpose:		Sets the object reference to the observer object.
// Arguments:	observerObject - The object that will be called when this object changes.
//
ScaleSelector.prototype.SetObserver = function( observerObject )
{
	// Set the observer object
	this.observerObject = observerObject;
	
	// Give it our current state.
	this.observerObject.SetScaleNotes( this.GetNotes() );
}

