/* Copyright 2008 we-lab-doc! (http://www.we-lab-doc.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.we_lab_doc.spacecard.model

import com.we_lab_doc.spacecard.model.abstracts.*
import com.we_lab_doc.spacecard.utils.*

/**
 * @author Shigeru GOUGI
 * @since 0.1
 *        <p/>
 *        Created: February 13, 2008
 */ 
class CrossLink extends Link  {
	Link bind(SpaceCard owner, SpaceCard target) {
		assert targets == null || targets.size() == 0
		assert owner != null && target != null		
		addToTargets(owner)
		addToTargets(target)
		owner.addToLinks(this)
		target.addToLinks(this)
		return this
	}
	Link unbind() {
		if(targets) {
			def clone = ModelUtils.cloneCollection( targets )
			clone*.removeFromCounterLinks(this)
		}
		if(owners) {
			def clone = ModelUtils.cloneCollection( owners )
			clone*.removeFromLinks(this)
		}
		return this
	}
	SpaceCard getTarget(SpaceCard myCard) {
		assert myCard != null
		for (target in targets) {
			if(target.id != myCard.id) return target
		}
		return null
	}
	////
	static Link create() {
		return create(null, null)
	}	
	static Link create(String name) {
		return create(name, null)
	}
	static Link create(String name, String description) {
		return create( [name:name,description:description])
	}
	static Link create(params) {
		assert params != null
		if(!params.creator) {
			def acs = SpaceCardModel.accessControlService
			assert acs != null
			params.creator = acs.getLoggedInUser()
		}
		return new CrossLink(params)
	}	
	/////////////////////////////////////////////
	def addToTargets(SpaceCard obj) {
		if(obj == null) return
		return CollectionBugEvasion.addToForBidirectionalManyToMany(
				this, Set.class, obj, SpaceCard.class, "targets", "counterLinks"
			)
	}
	def removeFromTargets(SpaceCard obj) {
		if(obj == null) return
		return CollectionBugEvasion.removeFromForBidirectionalManyToMany(
				this, obj, "targets", "counterLinks"  
			)
	}
	/////////////////////////////////////////////
	protected boolean constraintsTargets() {
		return targets?.size() == 2
	}
	/////////////////////////////////////////////
	static hasMany     = [targets:SpaceCard]
	static belongsTo   = [SpaceCard]	
	static constraints = {
		targets(
			nullable:true, // don't delete
			validator:{val, obj ->
				if(obj.targets == null) {
					return ['null.message']
				} 
				if(!obj.constraintsTargets()) {
					return ['invalid.validator.message']
				}
			}
		)
	}
	/////////////////////////////////////////////
}
