
// requires scale object

// constructor
Chord = function (tonic,chord_type,config) 
{

	this.notes = [ "A","Bb","B","C","C#","D","Eb","E","F","F#","G","G#" ];

	if (typeof(config)!='object') config = new Object();
	var default_config = 	{
							scale : null,
							first : null,
							third : null,
							fifth : null,
							extension : null, // {5th,7th,maj7th,etc}
							additions : [],
							scale_notes : null,
							chord_notes : null
							};
	// setup config
	for (var i in default_config)
	{
		if (typeof config[i] == 'undefined')
			config[i] = default_config[i];
	}
	for (var i in config) this[i] = config[i];	

	this.chord_notes = []; // array of the notes in the chord
	
	// default tonic is C
	if (typeof tonic == 'undefined') tonic = 'C';
	this.tonic = tonic;
	if (typeof chord_type == 'undefined') chord_type = 'major';
	this.chord_type = chord_type;
	
	this.init();
};

// object
Chord.prototype = 
{

	init : function()
	{
		this.init_scale_notes();
		this.init_triad();
		this.do_extension();
		this.do_additions();
		this.chord_notes = this.get_notes();
		this.name = this.get_chord_name();
	},

	init_scale_notes : function()
	{
		this.scale = new Scale(this.tonic,'major');
		this.scale_notes = (this.scale.scale_notes);
	},
	
	init_triad : function()
	{
		this.first = this.scale_notes[0];
		this.third = this.scale_notes[2];
		this.fifth = this.scale_notes[4];
		
		if (this.chord_type == 'minor') //minor chord
		{
			this.third = this._note_addition(this.third, -1); // bring the 3rd down one step
		} 
		 else if (this.chord_type == 'aug') // augmented chord
		{
			this.fifth = this._note_addition(this.fifth, 1); // move the fifth up one step
		}
		 else if (this.chord_type == 'dim') // diminished chord
		{
			this.third = this._note_addition(this.third, -1); // bring the 3rd down one step
			this.fifth = this._note_addition(this.fifth, -1); // bring the 5th down one step
			this.additions.dim_note = this._note_addition(this.scale_notes[6], -2); // add a 4th note, the diminished note which is the 7th brought down two steps
		}
		return;
	},
	
	// add an extension (5th, 7th, maj7th, etc)
	do_extension : function ()
	{
			
		if (this.extension==null || this.extension=='' || this.extension=='none') return;
		
		// do the seventh
		if (this.extension.search(/maj/i) != -1) // seventh is major
		{
			this.additions.seventh = this.scale_notes[6];
		}
		else // seventh is minor
		{			
			this.additions.seventh = this._note_addition(this.scale_notes[6], -1);
		}

		if (this.extension.search(/7/i) != -1) // seventh already done, so return
		{
			return;
		}
		
		// not a seventh, so add 9th
		// ninth chord (add2)
		this.additions.ninth = this.scale_notes[1];

		if (this.extension.search(/9/i) != -1) // ninth already done, so return
		{
			return;
		}

		// not a ninth, so add 11th
		// 11th chord (add4)
		this.additions.eleventh = this.scale_notes[3];

		if (this.extension.search(/11/i) != -1) // ninth already done, so return
		{
			return;
		}

		// not an eleventh, so must be a 13th
		// 13th chord (add6)
		this.additions.thirteenth = this.scale_notes[5];
		delete this.additions.eleventh; // there is not eleventh with a 13th

		// and done
		return;
	},
	
	do_additions : function()
	{
		for(var i=0; i<this.additions.length; i++)
			this.do_addition(this.additions[i]);
	},	
	do_addition : function (addition)
	{
		// check for suspended notes
		if (addition.search(/sus/i) != -1)
		{
			// addition is a suspended second or fourth
            if (addition.search(/2/) != -1)
			{
				this.third = null; // no third with a suspended 2nd
				this.additions.second = this.scale_notes[1];
			} 
			else if (addition.search(/4/) != -1)
			{
				this.third = null;
				this.additions.second = this.scale_notes[3];
			}
            return;
		} // end if (suspended note)

		// check for 5th modification
        if (addition.search(/5/) != -1)
		{
			// fifth dim or aug
			if (addition.search(/aug/i) != -1)
			{
				// augmented 5th
				this.fifth = this._note_addition(this.fifth, 1);
			} 
			else if (addition.search(/dim/i) != -1)
			{
				// diminished 5th
				this.fifth = this._note_addition(this.fifth, -1);
			}
			return;
		} // end if (5th modification)

		// check for 6th
		if (addition.search(/6/) != -1)
		{
			// 6th
			this.additions.sixth = this.scale_notes[5];
			return;
		} // end if (6th)
		
		// check for 9th modification
		if (addition.search(/9/) != -1)
		{
			// ninth add, dim or aug
			if (addition.search(/aug/i) != -1)
			{
				// augmented 9th
				this.additions.ninth = this._note_addition(this.scale_notes[1] , 1);
			} 
			else if (addition.search(/dim/i) != -1)
			{
				// diminished 9th
				this.additions.ninth = this._note_addition(this.scale_notes[1] , -1);
			} 
			else 
			{
				// add9
				this.additions.ninth = this.scale_notes[1];
			}
			return;
		} // end if (9th modification)

		// check for 11th modification
		if (addition.search(/11/) != -1)
		{
			// 11th add, dim or aug
			if (addition.search(/aug/i) != -1)
			{
				// augmented 11th
				this.additions.eleventh = this._note_addition(this.scale_notes[3] , 1);
			} 
			else if (addition.search(/dim/i) != -1)
			{
				// diminished 11th
				this.additions.eleventh = this._note_addition(this.scale_notes[3] , -1);
			
			}
			else 
			{
				// add11
				this.additions.eleventh = this.scale_notes[4];			
			}
			return;
		} // end if (11th modification)
	},
	
	get_notes : function()
	{
		var notes = [ ];
		if (this.first != null)
			notes.push(this.first);
		if (this.third != null)
			notes.push(this.third);
		if (this.fifth != null)
			notes.push(this.fifth);	

		// additions
		var additions = ['sixth','seventh','second','ninth','eleventh','thirteenth','dim_note'];
		var a;
		for (var i=0; i<additions.length; i++)
		{
			a = additions[i];
			if (typeof this.additions[a] != 'undefined' && this.additions[a] != null)
			{
				notes.push(this.additions[a]);
			}
		}
		return notes;
	},
	
	get_chord_name : function()
	{
		var name = this.tonic;
		if (this.chord_type != 'major')
			name += ' ' + this.chord_type;
		name += ' ' + this.extension;
		for (var i=0; i<this.additions.length; i++)
			name += ' ' + this.additions[i];
		return name;
	},
		
	_note_addition : function (note, amount, return_index)
	{
		if (typeof return_index == 'undefined') return_index = false;
		// get starting index
		for (var i=0; i<this.notes.length; i++)
		{
			if (note==this.notes[i])
				currentIndex = i;
		}
		var toBeIndex = currentIndex + amount;
        
        if (toBeIndex < 0)
		{
			toBeIndex = toBeIndex + this.notes.length;
		} 
		else if ( toBeIndex > (this.notes.length-1) )
		{
			while ( toBeIndex > (this.notes.length-1) )
			{
				toBeIndex = toBeIndex - this.notes.length;
			}
		}
        return (return_index) ? toBeIndex : this.notes[toBeIndex];
	}
};