//========== Topic ===================
function topic(id){
	this.parent=bareTopic
	this.parent(id)
	this.nameList=new Array()
	this.occurrences=new Array()
    this.subjectIdentity=null
}

// ====== Topic Interface =========
topic.prototype.addBaseName=_add_basename
topic.prototype.addOccur=_add_occurrence
topic.prototype.deleteOccur = _delete_occurrence

topic.prototype.getNamesFiltered=_get_names_filtered
topic.prototype.getNamesFilteredAny=_get_names_filtered_any
topic.prototype.getOccursFiltered=_get_occurs_filtered	

topic.prototype.erase=_top_erase
topic.prototype.toString=topicToString
topic.prototype.setIdentity=_set_identity
topic.prototype.getIdentity=_get_identity

function _set_identity(subject_identity){
	this.subjectIdentity=subject_identity
}

function _get_identity(){
	return this.subjectIdentity
}

function _delete_occurrence(occurrence) {
	if (!occurrence) {
		return
	}

	var occur = occurrence
	occur.erase()

	var occurs = this.getOccursFiltered()
	var temp = []
	for (var o in occurs) {
		if (occurs[o] != occurrence) {
			temp.push(occurs[o])
		}
	}

	this.occurrences = temp
	temp = null
}

function topicToString(){
	return "[topic]"
}

function _add_basename(name){
	var n1
	if (name){
		n1=this.nameList
		n1[n1.length]=name
	}
}

function _add_occurrence(Occur){
	var n1
	if (Occur){
		n1=this.occurrences
		n1[n1.length]=Occur
	}
}

function _get_occurs_filtered(filters){
	if (!filters){return this.occurrences}

	var results=new Array(),o,f,s,foundoccur
	var theOccur, theScope,scopes
	// Check for unconstrained scope
	for (f in filters){
		if (filters[f].topic=='st-unconstrained'){
			return this.occurrences
		}
	}
	var filter,topics, oc
	// Loop over all occurrences
	for (o in this.occurrences){
		/*	For each, get its scopes
			For each scope, is it in the filters?
			If yes, add this occurrence to results 
			and go to next occurrence
		*/
		oc=this.occurrences[o]
		foundoccur=false
		scopes=oc.getScopes()
		// Check scopes
		for (s in scopes){
			if (foundoccur){break}
			theScope=scopes[s]
			// Check filters
			for (f in filters){
				if (theScope.topic==filters[f].topic)
				{
					results.push(oc)
					foundoccur=true
					break
				}
			}

		}
	}
	return results
}

function _get_names_filtered(filters){
/*
	Return an Array of name objects, filtered
	filtered using the optional list of filters.
	A filter is a scope object.  Names having 
	scopes matching all the filter items
	are accepted.
*/
	// If not filter supplied, return all names
	if (!filters || !filters.length || filters[0]=='st-unconstrained'){
		return this.nameList
	}

	//Check each name against the filters
	var results=[]
	var n,f,s
	var theName, theScope,namescopes
	var thefilter
	var candidate = false

	for (n in this.nameList){
		theName=this.nameList[n]
		for (f in filters){
			thefilter=filters[f]
			candidate=false
			namescopes=theName.getScopes()
			for (s in namescopes){
				theScope=namescopes[s]
				candidate=(theScope.topic==thefilter)
				if (candidate){break}
			}
			if (candidate) {
				results.push(theName)
				break
			}			
		}
	}
	return results
}

function _get_names_filtered_any(filters){
/*
	Return an Array of name objects, filtered
	filtered using the optional list of filters.
	A filter is a scope object.  Names having 
	scopes matching any of the filter items
	are accepted.
*/
	// If not filter supplied, return all names
	if (!filters||filters[0]=='st-unconstrained'){
		return this.nameList
	}

	//Check each name against the filters
	var results=new Array(),n,f,s,foundname
	var theName, theScope,namescopes
	var inFilter,thefilter

	for (n in this.nameList){
		theName=this.nameList[n]
		for (f in filters){
			inFilter=false
			thefilter=filters[f]
			namescopes=theName.getScopes()
			for (s in namescopes){
				theScope=namescopes[s]
				inFilter=(theScope.topic==thefilter)
				if (inFilter){
					results.push(theName)
					break
				}
			}
		}
	}
return results		
}

/* =============================================
	Remove and erase all topic components.

	for each name:
		erase name
		remove name
	for each occurrence:
		erase occurrence
		remove occurrence
	for subjectIdentity:
		erase subjectIdentity
		remove subjectIdentity
	remove instanceOf
   ============================================= */
function _top_erase(){
	var n,nn
	var o,oo
	var si

	// Names
	nn=this.getNamesFiltered()
	if (nn){
		while (nn.length){
			n=nn[nn.length-1]
			n.erase()
			n=null
			nn.length-=1
		}
	}
	this.nameList=null

	// Occurrences
	oo=this.getOccursFiltered()
	while (oo&&oo.length){
		o=oo[oo.length-1]
		o.erase()
		o=null
		oo.length-=1
	}
	this.occurrences=null
	this.id=''
	this.instanceOf=''

	// @@TODO: Deal with subjectIdentity
}



// =============== Base name =============

function baseName(label){
	this.parent=scopedObject
	this.parent()
	this.name=label||''
	this.addScope(new scope('st-unconstrained'))
}

// ====== Interface =========
baseName.prototype.getNameString=_get_namestring
baseName.prototype.erase=_name_erase
baseName.prototype.toString=baseNameToString
function baseNameToString(){
	return "[baseName]"
}

function _get_namestring(){
	return this.name
}	

/* ==========================================
	Remove all components of the name.

	for each scope:
		erase scope
		remove scope
	remove label
   ==========================================*/
function _name_erase(){
	var s,ss

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


//--------- Occurrence -----------------

function occur(id){
	this.parent=scopedTopic
	this.parent(id)
	this.resourceRef=''
	this.data=''
}


// ====== Interface =========
occur.prototype.getResource=_get_resource
occur.prototype.getData=_get_data
occur.prototype.getResourceOrData=_get_resource_or_data
occur.prototype.erase=_occur_erase

function _get_resource(){
	return this.resourceRef
}
function _get_data(){
	return this.data
}
function _get_resource_or_data(){
	if (this.data){return this.data}
	else {return this.resourceRef}
}	

/* ==========================================
	Remove all components of the occurrence.

	for each scope:
		erase scope
		remove scope
	remove resourceRef
	remove data
	remove instanceOf
   ==========================================*/
function _occur_erase(){
	var s,ss
	// Scopes
	ss=this.getScopes()
	while (ss&&ss.length){
		s=ss[ss.length]
		s.erase()
		s=null
		ss.length-=1
	}
	this.scopes=null

	this.resourceRef=null
	this.data=null
	this.instanceOf=null
}	


occur.prototype.toString=occurToString
function occurToString(){
	return "[occurrence]"
}

//------- Subject Identity ------------------

function subjectIdentity(id){
	this.id=id||''
    this.resourceRef=''
    this.topicRefs=[]
    this.subjectIndicatorRefs=[]
}    

// ====== Interface =========
subjectIdentity.prototype.getResourceRef=_get_resourceRef
subjectIdentity.prototype.changeResourceRef=_change_resource_ref
subjectIdentity.prototype.getTopicRefs=_get_topicRefs
subjectIdentity.prototype.getSubjectIndicators=_get_subjectIndicatorRefs
subjectIdentity.prototype.setResourceRef=_set_resourceRef
subjectIdentity.prototype.addTopicRef=_add_topicRef
subjectIdentity.prototype.addSubjectIndicatorRef=_add_subjectIndicatorRef

subjectIdentity.prototype.toString=subjectIdentityToString

function subjectIdentityToString(){
	return "[subjectIdentity]"
}
function _get_topicRefs(){
	return this.topicRefs
}

function _get_subjectIndicatorRefs(){
	return this.subjectIndicatorRefs
}

function _get_resourceRef(){
	return this.resourceRef
}

function _get_resourceuri(){
	var resource=this.getResourceRef()
	if (!resource){return ''}
	return resource.getLocal()||resource.getUri()
}

function _add_subjectIndicatorRef(subjIndicatorRefObj){
	var subref=this.subjectIndicatorRefs
	subref.push(subjIndicatorRefObj)
}

function _add_topicRef(topicRefObj){
	var toprefs=this.topicRefs
	toprefs.push(topicRefObj)
}

function _set_resourceRef(resourceRef){
	this.resourceRef=resourceRef
}


// Change the reference of the referenceRef, if there is one,
// else ignore
function _change_resource_ref(newuri){
	if (!this.resourceRef){return}
	this.resourceRef.setRef(newuri)
}

