/*
 * ActivityGroup.java
 *
 * Created 12.10.2000
 * Documented 7.7.2001
 */

package timetable.data;

import java.util.Vector;
import timetable.util.*;
/** Reprezntace skupiny aktivit v rozvrhovacím problému. Tato třída také umožňuje dynamické přidávání a odebírání activit.
 * @see timetable.data.Activity
 * @author  Tomáš Müller
 * @version 1.0
 */
public class ActivityGroup extends java.lang.Object implements java.io.Serializable{
    /** Množina aktivit, reprezentovaná pomocí třídy java.util.Vector */
    protected Vector activities = new Vector();
    /** Příznak určující změnu */
    public boolean changed = false;
    
    /** Konstruktor. */
    public ActivityGroup() {
    }
    
    /** Konstruktor.
     * @param activity po vytvoření třídy vloží activitu <CODE>activity</CODE>
     */
    public ActivityGroup(Activity activity) {
        activities.add(activity);
    }
    
    /** Konstruktor.
     * @param activity po vytvoření třídy vloží pole activit <CODE>activity</CODE>
     */
    public ActivityGroup(Activity[] activity) {
        for (int i=0; i<activity.length;i++)
            activities.add(activity[i]);
    }
    
    
    /** Přidání activity do seznamu.
     * @param activity přidávaná activita
     */
    public void add(Activity activity) {
        activities.add(activity);
        changed = true;
    }
    
    /** Změnila se množina aktivit?
     * @return <code>true</code> pokud ano
     */    
    public boolean isChanged() {
        return changed;
    }
    
    /** Přidání aktivity do seznamu, pokud tato activita ještě v seznamu není.
     * @param activity přidávaná activita
     */
    public void addIfIsNot(Activity activity) {
        if (indexOf(activity)<0) add(activity);
    }
    
    /** Přidání aktivit do seznamu, pokud tyto activity ještě v seznamu nejsou.
     * @param activities seznam přidávaných activit
     */
    public void addIfIsNot(ActivityGroup activities) {
        for (int i=0;i<activities.size();i++)
            addIfIsNot(activities.get(i));
    }

    /** Odebrání aktivity ye seznamu.
     * @param activity odebíraná aktivita
     */
    public void remove(Activity activity) {
        activities.remove(activity);
        changed = true;
    }
    
    /** Odebrání všech aktivit ze seznamu. */
    public void removeAll() {
        activities.clear();
    }
    
    /** Získání počtu aktivit v seznamu 
     * @return počet aktivit v seznamu
     **/
    public int size() {
        return activities.size();
    }
        
    /** Vrátí aktivitu s pořadovým číslem i. (Čísla jdou od <CODE>0</CODE> do <CODE>size()-1</CODE>).
     * @param i pořadové číslo aktivity
     * @return daná aktivita
     */
    public Activity get(int i) {
        try {
            return (Activity) activities.get(i);
        } catch (java.lang.ArrayIndexOutOfBoundsException e) {
            return null;
        }
    }
    
    /** Vrátí index aktivity.
     * @param actitivy hledaná aktivita
     * @return index aktivity v seznamu, -1 pokud tam není.
     */
    public int indexOf(Activity activity) {
        return activities.indexOf(activity);
    }
    
    /** Vrátí jinou instanci této třídy obsahující stejnou skupinu aktivit.
     * @return jiná skupina stejných aktivit
     */
    public Object clone() {
        ActivityGroup g = new ActivityGroup();
        for (int i=0;i<size();i++)
          g.add(get(i));
        return g;
    }
    
    /** Zjištuje, zda-li některá z aktivit vyžaduje příslušný zdroj.
     * @param resource zdroj
     * @return index první aktivity, která zdroj vyžaduje. -1 pokud taková aktivita neexistuje.
     */
    public int containsResource(Resource resource) {
        for (int i=0;i<size();i++) 
            if (get(i).resources.contains(resource)>=0) return i;
        return -1;
    }

    /** Zjišťuje, zda-li některá z aktivity vyžaduje skupinu zdrojů.
     * @param resource skupina zdrojů
     * @return index první aktivity, která danou skupinu vyžaduje. -1 pokud taková aktivita neexistuje.
     */    
    public int containsResources(ResourceGroup resources) {
        for (int i=0;i<size();i++) 
            if (get(i).resources.indexOf(resources)>=0) return i;
        return -1;
    }

    /** Vrátí řetězec, čárkami oddělený seznam jmen aktivit.
     * @return seznam jmen aktivit
     */
    public String toString() {
        java.lang.StringBuffer s = new java.lang.StringBuffer();
        for (int i=0;i<size();i++) {
            if (i>0) s.append(",");
            s.append(get(i).name);
        };
        return s.toString();
    }
    
    /** Zápis seznamu aktivit do streamu
     * @param out stream
     */
   private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
       out.writeObject(activities);
   }

   /** Přečtení seznamu aktivit ze streamu
    * @param in stream
    * @return přečtený seznam aktivit
    */
   private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException {
       activities = (Vector) in.readObject();
   }
   
  /** Zápis seznamu aktivit do streamu. Volá metodu Activity.write pro zápis aktivity. Maže přízank změny <code>changed</code>.
   * @param out stream
   * @param allResources množina všech zdrojů
   */
   protected void write(java.io.ObjectOutputStream out, ResourceGroup allResources) throws java.io.IOException {
       out.writeInt(size());
       for (int i=0;i<size();i++)
           get(i).write(out,allResources);
       changed = false;
   }
   
   /** Přečtení seznamu aktivit ze streamu. Volá metodu Activity.read pro čtení aktivity.
    * @param in stream
    * @param config globální konfigurace
    * @param allResources množina všech zdrojů
    * @return přečtený seznam aktivit
    */
   protected static ActivityGroup read(java.io.ObjectInputStream in, Config config, ResourceGroup allResources) throws java.io.IOException, java.lang.ClassNotFoundException, TimetableException {
       ActivityGroup g = new ActivityGroup();
       int size = in.readInt();
       for (int i=0;i<size;i++)
           g.add(Activity.read(in,config,allResources));
       return g;
   }
    
}
