// ====== Association ==========
function association(id){
	this.parent=scopedTopic
	this.parent(id)
	this.members=new Array()
}

// ====== Interface =========
association.prototype.addMember=_add_member
association.prototype.getMembers=_get_members
association.prototype.getMemberByRoleType=_get_member_by_role_type
association.prototype.getID=_get_id
association.prototype.erase=_assoc_erase
association.prototype.toString=assocToString
association.prototype.getPlayerIndexByMemberRoleId = _get_player_index_by_member_role_id

function assocToString(){
	return "[association]"
}

function _get_id(){
	if (this.id){
		return this.id
	}
	return ''
}

/* ================================================
	Add member to association.  We want to avoid
	duplicate members, so we check to see if a member
	having the same id or roletype already exists.

	If it does, we will add any players for the candidate
	member to the existing one instead.
   ================================================ */
function _add_member(member){
	var id,role
	var m,members,Member,theMember
	var p,newplayers,player
	members=this.getMembers()
	for (m in members){
		Member=members[m]
		id='';role=''
		id=Member.id
		role=Member.roleSpec
		if ((id&&id==member.id)||(role==member.roleSpec)){
			// Transfer all roles to the existing member
			newplayers=member.getPlayers()
			for (p in newplayers){
				Member.addPlayer(newplayers[p])
			}
			return
		}
	}
	if (member){
		var m=this.members
		m[m.length]=member
	}
}

function _get_members(){
	return this.members
}

function _get_member_by_role_type(roleSpec){
	// Assume we can only have one member with
	// a particular role.
	var i,m
	if (!roleSpec||!this.members){return false}
	for (i=0; i < this.members.length; i++){
		m=this.members[i]
		if (!m){continue}
		
		if (m.roleSpec==roleSpec){
			return m
		}
	}
	return false
}	

/* ===========================================
	Erase all components of the association.

	for each member:
		erase member
		remove member
	for each scope:
		erase scope
		remove scope
	remove parent reference
	remove instanceOf reference
   ===========================================*/
function _assoc_erase(){
	var m,mm
	var s,ss
	// Members
	mm=this.getMembers()
	while (mm&&mm.length){
		m=mm[mm.length]
		if (m){
			m.erase()
			m=null
		}
		mm.length-=1
	}
	this.members=null

	// Scopes
	ss=this.getScopes()
	while (ss&&ss[ss.length]){
		s=ss[ss.length]
		s.erase()
		s=null
		ss.length-=1
	}
	this.scopes=null

	this.instanceOf=null
}


// Return dictionary keyed by member type.  Each item is a list of player topics
function _get_player_index_by_member_role_id() {
	var member, members
	var player, players
	var player_dict = {}

	members = this.getMembers()
	
	var role_id
	for (var m = 0; m < members.length; m++){
		member = members[m]
		role_id = member.roleSpec
		players = member.getPlayers()
		player_dict[role_id] = players
	}
	return player_dict
}

//--------- Member ------------------

function member(roleSpec){
	this.roleSpec=roleSpec||''
	this.rolePlayers=new Array()
}

// ====== Interface =========
member.prototype.addPlayer=_add_player
member.prototype.getPlayers=_get_players
member.prototype.erase=_member_erase


/* ================================================
	Add player to association member.

	@@@FIXME - need to find a way to update the topic
	map's index of associations by topic? - but the
	member doesn't know the owning topicmap.
   ================================================ */
function _add_player(playerTopic){
	var rp
	if (playerTopic){
		rp=this.rolePlayers
		rp[rp.length]=playerTopic
	}
}

// Players are topics (not just topic ids)
function _get_players(){
	return this.rolePlayers
}	

function _member_erase() {
	var p,pp
	this.roleSpec=null
	pp=this.getPlayers()
	while (pp&&pp.length){
		p=pp[pp.length]
		p=null
		pp.length-=1
	}
	this.rolePlayers=null
}
