/*
 * ActivityDepenedenceGroup.java
 *
 * Created on 21. říjen 2000, 15:52
 * Documented 8.7.2001
 */

package timetable.data;

import java.util.Vector;
/** Reprezentace skupiny závislostí mezi aktivitami.
 *
 * @author  Tomáš Müller
 * @version 1.0
 */
public class ActivityDependenceGroup extends Object {
    /** Závislosti reprezentované jako java.util.Vector */
    protected Vector dependences = new Vector();
    
    /** Konstruktor. */
    public ActivityDependenceGroup() {
    }
    
    /** Konstruktor.
     * @param dep po vytvoření skupiny se do ní vloží závislost dep
     */
    public ActivityDependenceGroup(ActivityDependenceInterface dep) {
        dependences.add(dep);
    }

    /** Konstruktor.
     * @param dep po vytvoření skupiny se do ní vloží závislosti dep
     */
    public ActivityDependenceGroup(ActivityDependenceInterface[] dep) {
        for (int i=0;i<dep.length;i++)
            dependences.add(dep[i]);
    }
        
    /** Přidání nové závislosti
     * @param dep závislost
     */
    public void add(ActivityDependenceInterface dep) {
        dependences.add(dep);
    }
    
    /** Odebrání závislosti ze skupiny
     * @param deo závislost
     */
    public void remove(ActivityDependenceInterface dep) {
        dependences.remove(dep);
    }
    
    /** Odebrání všech závislostí ze skupiny */
    public void removeAll() {
        dependences.clear();
    }
    
    /** Vrátí počet závislostí ve skupině.
     * @return počet závislostí
     */
    public int size() {
        return dependences.size();
    }
    
    /** Vrátí i-tou závislost
     * @param i index do skupiny závislostí
     * @return i-tá závislost
     */
    public ActivityDependenceInterface get(int i) {
        try {
            return (ActivityDependenceInterface) dependences.get(i);
        } catch (java.lang.ArrayIndexOutOfBoundsException e) {
            return null;
        }
    }
    
    /** Spočítá počet závislostí, ve kterých se vyskytuje daná aktivita.
     * @param a aktivita
     */
    public int countDependences(Activity a) {
        int sum=0;
        for (int i=0;i<size();i++)
            if (get(i).participate(a)) sum++;
        return sum;
    }
    
    /** Otestuje všechny závislosti.
     * @return true, pokud jsou všechny splněny
     */
    public boolean isOK() {
        for (int i=0;i<size();i++) 
            if (!get(i).isOK()) return false;
        return true;
    }
    
    /** Otestuje všechny závislosti s danou aktivitou.
     * @param a aktivita
     * @param start začátek aktivity
     * @return true, pokud jsou splněny
     */
    public boolean isOK(Activity a, int start) {
        for (int i=0;i<size();i++) 
            if (!get(i).isOK(a,start)) {
                return false;
            }
        return true;
    }
    
    /** Otestuje všechny závislosti s danou aktivitou, kde druhá aktivita nelze přeplánovat. Pouze tyto závislosti musejí být splěny, ostatní lze řešit vyhozením druhé z aktivit z rozvrhu.
     * @param a aktivita
     * @param start začátek aktivity
     * @return true, pokud jsou splněny
     */
    public boolean isFixedOK(Activity a, int start) {
        for (int i=0;i<size();i++) {
            Activity b = get(i).getAnotherActivity(a);
            if (b!=null && !b.canReschedule && !get(i).isOK(a,start)) 
                return false;
        }
        return true;
    }

    /** Vrátí všechny aktivity které jsouv v konfliktu s danou aktivitou kvůli některé ze závislostí. 
     * @param a aktivita
     * @param start začátek aktivity
     * @return množina konfliktních aktivit
     */
    public ActivityGroup getConflictActivities(Activity a, int start) {
        ActivityGroup g = new ActivityGroup();
        for (int i=0;i<size();i++) {
            if (!get(i).isOK(a,start))
                g.addIfIsNot( get(i).getAnotherActivity(a));
        }
        return g;
    }
    
    /** Zápis skupiny závislostií do streamu
     * @param out stream
     * @param allActivities množina všech aktivit
     */
   public void write(java.io.ObjectOutputStream out, ActivityGroup allActivities) throws java.io.IOException {
       out.writeInt(size());
       for (int i=0;i<size();i++) {
           out.writeObject(get(i).getClass().getName());
           get(i).write(out, allActivities);
       }
   }

   /** Přečtení skupiny závislostí ze streamu.
     * @param in stream
     * @param allActivities množina všech aktivit
     * @return načtená skupina závislostí
     */
   public static ActivityDependenceGroup read(java.io.ObjectInputStream in, ActivityGroup allActivities) throws java.io.IOException, java.lang.ClassNotFoundException, java.lang.NoSuchMethodException, java.lang.InstantiationException, java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException {
       int size = in.readInt();
       ActivityDependenceGroup g = new ActivityDependenceGroup();
       for (int i=0;i<size;i++) {
           String className = (String) in.readObject();
           Class c = Class.forName(className);
           Object o = c.getConstructor(new Class[] {}).newInstance(new Object[] {});
           g.add(((ActivityDependenceInterface)o).read(in, allActivities));
       }
       return g;
   }

}