/*
 * MiningMart Version 1.0
 * 
 * Copyright (C) 2006 Martin Scholz, Timm Euler, 
 *                    Daniel Hakenjos, Katharina Morik
 *
 * Contact: miningmart@ls8.cs.uni-dortmund.de
 *
 * A list of contributing developers (other than the copyright 
 * holders) can be found at
 * http://mmart.cs.uni-dortmund.de/downloads/download.html
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program, see the file MM_HOME/LICENSE; if not, write
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 */
package edu.udo.cs.miningmart.gui.model;


import java.util.Collection;
import java.util.Iterator;

import org.musoft.limo.application.Application;
import org.musoft.limo.application.Resource;
import org.musoft.limo.model.Model;
import org.musoft.limo.model.ModelConnectionElement;
import org.musoft.limo.model.ModelFigureElement;
import org.musoft.limo.model.ModelPrimitiveAttribute;

import edu.udo.cs.miningmart.exception.M4Exception;
import edu.udo.cs.miningmart.gui.application.CreateTransitionDialog;
import edu.udo.cs.miningmart.gui.application.DeleteTransitionDialog;
import edu.udo.cs.miningmart.gui.application.MiningMartApplication;
import edu.udo.cs.miningmart.m4.Case;
import edu.udo.cs.miningmart.m4.Chain;
import edu.udo.cs.miningmart.m4.Concept;
import edu.udo.cs.miningmart.m4.M4Interface;
import edu.udo.cs.miningmart.m4.OpParam;
import edu.udo.cs.miningmart.m4.Step;
import edu.udo.cs.miningmart.m4.utils.Print;

/**
 * This is a <code>ModelConnectionElement</code> between Steps and/or Chains.
 * @author Daniel Hakenjos
 * @version $Id: StepTransition.java,v 1.3 2006/04/11 14:10:15 euler Exp $
 */
public class StepTransition extends ModelConnectionElement{

	private Case thecase;
	
	private MiningMartApplication app;
	
	private String name;
	
	private boolean deleteInDatabase=true;

    /**
     * Constructs new <code>StepTransition</code>.
     */
	public StepTransition(){
		super();
	}

	/**
	 * Sets the flag that this object could be deleted in the database.
	 */    
	public void setDeleteInDatabase(boolean bool){
		this.deleteInDatabase=bool;
	}
    
	/**
	 * Gets the flag indicating that this obkect can be deleted in the database.
	 */
	public boolean canDeleteInDatabase(){
		return this.deleteInDatabase;
	}

	
	/**
	 * Constructs new <code>StepTransition</code> with the given parameters.
	 * @param name the name of the output- and input-concept
	 */
	public StepTransition(MiningMartApplication app,Case thecase,String name, Model model,ModelFigureElement start, ModelFigureElement end) {
		super(name, model);
		
		this.name=name;
		this.thecase=thecase;
		this.setStart(start);
		this.setEnd(end);
		this.app=app;
		
		refreshName();
        //getAttribute("source").setAccess(ModelAttribute.ACCESS_READ);
        //getAttribute("target").setAccess(ModelAttribute.ACCESS_READ);
	}
	
	/**
	 * Refreshs the name of the transition.
	 * If TheOutputConcept or TheInputConcept exists then the name of the concept is the name of the transition.
	 */
	public void refreshName(){

		try{
			
			ModelFigureElement start=getStart();
			if (start instanceof MiningMartStep){
				Step step=((MiningMartStep) start).getStep();
				OpParam input=null,output=null;
				Iterator iter=step.getTheOperator().getOpParamsIterator();
				OpParam opparam;
				while (iter.hasNext()){
					opparam=(OpParam) iter.next();
					if (opparam.getName().equals("TheInputConcept")){
						input=opparam;
					}else
					if (opparam.getName().equals("TheOutputConcept")){
						output=opparam;
					}
				}
				
				if (output!=null){
					Collection params=step.getParameter(output,0);
					if ((params!=null)&&(params.size()>0)){
						iter=params.iterator();
						Concept concept;
						if (iter.hasNext()){
							concept=(Concept) iter.next();
							setName(concept.getName());				
						}else{
							setName(this.name);
						}
					}
				}else if (input !=null){
					Collection params=step.getParameter(input,0);
					if ((params!=null)&&(params.size()>0)){
						iter=params.iterator();
						Concept concept;
						if (iter.hasNext()){
							concept=(Concept) iter.next();
							setName(concept.getName());				
						}else{
							setName(this.name);
						}
					}
				}else{
					setName(this.name);
				}
			}
			
		}catch(M4Exception error){
			M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			setName(this.name);
		}

	}
	
	
    /**
     *Sets the <code>MiningMartApplication</code>.
     */
	public void setMMartApplication(MiningMartApplication app){
		if (this.app==null){
			this.app=app;
		}
	}

        /**
         *Gets the <code>MiningMartApplication</code>.
         */
	public MiningMartApplication getMMartApplication(){
		return app;
	}

        /**
         *Adds the transition as a dependency to the <code>Case</code>.
         */
	public boolean addTransitionToCase() {
		try{
			if ((getStart() instanceof MiningMartChain)&&(getEnd() instanceof MiningMartChain)){
				//Chain to Chain dependency
				MiningMartChain mchainstart=(MiningMartChain) getStart();
				MiningMartChain mchainend=(MiningMartChain) getEnd();
				Chain chainstart=mchainstart.getChain();
				Chain chainend=mchainend.getChain();
	
				CreateTransitionDialog dialog=new CreateTransitionDialog(null,chainstart,chainend);
				
				if (dialog.getExitAction()!=CreateTransitionDialog.OK){
					return false;
				}
				
				Step[] steps=new Step[]{dialog.getFromStep(),dialog.getToStep()};

				thecase.addStepDependency(steps[0],steps[1]);
				
				ModelFigureElement p=mchainstart.getParent();

				//sollte schon eine Verbiundung zwischen den Chains existieren,
				//dann bitte keine Transition mehr hinzufuegen
				if (p instanceof MiningMartCase){
					if (((MiningMartCase) p).existsTransition(mchainstart,mchainend)){
						return false;
					}
				}else if (p instanceof MiningMartChain){
					if (((MiningMartChain) p).existsTransition(mchainstart,mchainend)){
						return false;
					}
				}
	
			}else if ((getStart() instanceof MiningMartStep)&&(getEnd() instanceof MiningMartChain)){
				
				MiningMartStep mstepstart=(MiningMartStep) getStart();
				MiningMartChain mchainend=(MiningMartChain) getEnd();
				Step stepstart=mstepstart.getStep();
				Chain chainend=mchainend.getChain();

				CreateTransitionDialog dialog=new CreateTransitionDialog(null,stepstart,chainend);

				if (dialog.getExitAction()!=CreateTransitionDialog.OK){
					return false;
				}
				
				Step[] steps=new Step[]{dialog.getFromStep(),dialog.getToStep()};
				
				thecase.addStepDependency(stepstart,steps[1]);				
	
				//sollte schon eine Verbiundung zwischen Step und Chain existieren,
				//dann bitte keine Transition mehr hinzufuegen
				if (((MiningMartChain) mchainend.getParent()).existsTransition(mstepstart,mchainend)){
						return false;
				}
			}else if ((getStart() instanceof MiningMartChain)&&(getEnd() instanceof MiningMartStep)){
				
				MiningMartChain mchainstart=(MiningMartChain) getStart();
				MiningMartStep mstepend=(MiningMartStep) getEnd();

				Chain chainstart=mchainstart.getChain();
				Step stepend=mstepend.getStep();

				CreateTransitionDialog dialog=new CreateTransitionDialog(null,chainstart,stepend);

				if (dialog.getExitAction()!=CreateTransitionDialog.OK){
					return false;
				}

				
				Step[] steps=new Step[]{dialog.getFromStep(),dialog.getToStep()};
				
				thecase.addStepDependency(steps[0],stepend);

				//sollte schon eine Verbiundung zwischen Step und Chain existieren,
				//dann bitte keine Transition mehr hinzufuegen
				if (((MiningMartChain) mchainstart.getParent()).existsTransition(mchainstart,mstepend)){
						return false;
				}
	
			}else if ((getStart() instanceof MiningMartStep)&&(getEnd() instanceof MiningMartStep)){
				MiningMartStep mstepstart=(MiningMartStep) getStart();
				MiningMartStep mstepend=(MiningMartStep) getEnd();

				Step stepstart=mstepstart.getStep();
				Step stepend=mstepend.getStep();
				
				//sollte schon eine Verbiundung zwischen den Steps existieren,
				//dann bitte keine Transition mehr hinzufuegen
				if (stepstart.getTheCase().containsDependency(stepstart,stepend)){
					return false;
				}

				thecase.addStepDependency(stepstart,stepend);
			}else{
	
			}
		}catch(M4Exception error){
			M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			return false;
		}		
		return true;
	}

	public boolean canConnect(ModelFigureElement start, ModelFigureElement end) {
/*
		try{
		if (start instanceof MiningMartChain){
			if (end instanceof MiningMartChain){
				
				return !((MiningMartChain) start).getChain().dependencyExists(((MiningMartChain) end).getChain());

			}else if (end instanceof MiningMartStep){

				return !((MiningMartChain) start).getChain().dependencyExists(((MiningMartStep) end).getStep());

			}
		}else if (start instanceof MiningMartStep){
			if (end instanceof MiningMartChain){
				
				return !((MiningMartStep) start).getStep().dependencyExists(((MiningMartChain) end).getChain());

			}else if (end instanceof MiningMartStep){
				return !app.m4Interface.getCurrentCase().containsDependency(((MiningMartStep) start).getStep(),((MiningMartStep) end).getStep());
			}
		}
		
		}catch(M4Exception error){
			error.printStackTrace();
			return false;
		}
*/		
		
		return true;
	}

        /**
         *Gets the start-class.
         */
	protected Class getStartClass() {
		return ModelFigureElement.class;
	}

        /**
         *Gets the start-name.
         */
	protected String getStartName() {
		return "outgoing";
	}

        /**
         *Gets the end clas.
         */
	protected Class getEndClass() {
		return ModelFigureElement.class;
	}

        /**
         *Gets the end name.
         */
	protected String getEndName() {
		return "incoming";
	}

        /**
         *Gets the label of this <code>StepTranbsition</code>.
         */
    public String getLabel() {
        String t = ((ModelPrimitiveAttribute) getAttribute("trigger")).getString();
        String e = ((ModelPrimitiveAttribute) getAttribute("effect")).getString();
        String g = ((ModelPrimitiveAttribute) getAttribute("guard")).getString();

        if ("".equals(t)) t = null;
        if ("".equals(e)) e = null;
        if ("".equals(g)) g = null;
            
        String s = (t == null ? "" : t) + (g == null ? "" : "[" + g + "]") + (e == null ? "" : "/" + e);
        
        return ("".equals(s) ? null : s);
    }
    
	public String toString() {
		return getName() + ": " + getType();
	}

	public boolean canDestroy() {
		if (app.getViewMode()==Application.VIEWER){
			return false;
		}
		return true;
	}

    public String getType() {
        return Resource.getString("TRANSITION");
    }
    
	/**
         * Destroys this <code>StepTransition</code> and removes the dependency in the <code>Case</code>.
	 * @see org.musoft.limo.model.ModelElement#destroy()
	 */
	public void destroy() {

		if (app.getViewMode()==Application.VIEWER){
			//Im viewer-mode darf nicht zerstoert werden
			return;
		}
		
		if (this.canDeleteInDatabase()){
			
			try{
				if ((getStart() instanceof MiningMartChain)&&(getEnd() instanceof MiningMartChain)){
					//Chain to Chain dependency
					MiningMartChain mchainstart=(MiningMartChain) getStart();
					MiningMartChain mchainend=(MiningMartChain) getEnd();
					Chain chainstart=mchainstart.getChain();
					Chain chainend=mchainend.getChain();

					DeleteTransitionDialog dialog=new DeleteTransitionDialog(null,chainstart,chainend);
				
					if (dialog.getExitAction()!=DeleteTransitionDialog.OK){
						return;
					}
	
					thecase.removeStepDependency(dialog.getFromStep(),dialog.getToStep());

					if (!(chainstart.dependencyExists(chainend))){	
						//Nur wenn keine Verbindung mehr besteht darf die Transition geloescht werdn			
						super.destroy();
					}

	
				}else if ((getStart() instanceof MiningMartStep)&&(getEnd() instanceof MiningMartChain)){
				
					MiningMartStep mstepstart=(MiningMartStep) getStart();
					MiningMartChain mchainend=(MiningMartChain) getEnd();
					Step stepstart=mstepstart.getStep();
					Chain chainend=mchainend.getChain();
					DeleteTransitionDialog dialog=new DeleteTransitionDialog(null,stepstart,chainend);
				
					if (dialog.getExitAction()!=DeleteTransitionDialog.OK){
						return;
					}
	
					thecase.removeStepDependency(dialog.getFromStep(),dialog.getToStep());
	
					if (!(stepstart.dependencyExists(chainend))){	
						//Nur wenn keine Vrbindung mehr besteht darf die Transition geloescht werden			
						super.destroy();
					}
				}else if ((getStart() instanceof MiningMartChain)&&(getEnd() instanceof MiningMartStep)){
				
					MiningMartChain mchainstart=(MiningMartChain) getStart();
					MiningMartStep mstepend=(MiningMartStep) getEnd();

					Chain chainstart=mchainstart.getChain();
					Step stepend=mstepend.getStep();

					DeleteTransitionDialog dialog=new DeleteTransitionDialog(null,chainstart,stepend);
				
					if (dialog.getExitAction()!=DeleteTransitionDialog.OK){
						return;
					}
	
					thecase.removeStepDependency(dialog.getFromStep(),dialog.getToStep());
	
					if (!(chainstart.dependencyExists(stepend))){	
						//Nur wenn keine Verbindung mehr besteht darf die Transition geloescht werdn			
						super.destroy();
					}
				}else if ((getStart() instanceof MiningMartStep)&&(getEnd() instanceof MiningMartStep)){
				
					MiningMartStep mstepstart=(MiningMartStep) getStart();
					MiningMartStep mstepend=(MiningMartStep) getEnd();

					Step stepstart=mstepstart.getStep();
					Step stepend=mstepend.getStep();
				
					thecase.removeStepDependency(stepstart,stepend);
//					System.out.println("removed step dependency: ");
//					System.out.println(thecase.containsDependency(stepstart,stepend));
				
					super.destroy();
	
				}else{
	
				}
			}catch(M4Exception error){
				M4Interface.print.doPrint(Print.ERROR,error.getMessage(),error);
			}				}else{
			super.destroy();
		}


	}
	
	

	/**
	 * @see org.musoft.limo.model.ModelElement#canSetName(String)
	 */
	public boolean canSetName(String name) {
		return false;
	}

}
/*
$Log: StepTransition.java,v $
Revision 1.3  2006/04/11 14:10:15  euler
Updated license text.

Revision 1.2  2006/04/06 16:31:14  euler
Prepended license remark.

Revision 1.1  2006/01/03 09:54:36  hakenjos
Initial version!

*/
