package timetable.util;
/*
 * Config.java
 *
 * Created on 12. říjen 2000, 11:00
 * Documented 18. 7. 2001
 */

import java.util.Hashtable;
import java.io.*;

/** Třída spravující konfiguraci rozvrhovače. Při vytváření nového rozvrhu je tato konfigurace přečtena z konfiguračního souboru. Jde o tabulku klíč = hodnota.
 *
 * @author Tomáš Müller
 * @version 1.0
 */
public class Config extends java.lang.Object implements java.io.Serializable {
    /** počet slotů - klíč v konfiguračním souboru */
    public static String NR_SLOTS = "POCET_SLOTU";
    /** počet dnů - klíč v konfiguračním souboru*/
    public static String NR_DAYS = "POCET_DNU";
    /** maximální počet iterací - klíč v konfiguračním souboru*/
    public static String NR_TRIES = "POCET_ITERACI";
    /** Zkratky jmen dnů v týdnu */
    public static String DAY_OF_WEEK [] = new String[] {"Po","Ut","St","Ct","Pa","So","Ne"};

    /** zde je uložena konfigurace v paměti */
    public Hashtable configuration = new Hashtable();
    /** debug soubor (logování informací v průběhu řešení) - default */
    public static String LOG_FILE = "debug.log";
    /** zápis debug souboru */
    protected java.io.OutputStreamWriter osw = null;
    /** zápis debug souboru */
    protected java.io.FileOutputStream fos = null;
    /** konfigurační soubor */
    protected String file = null;
    /** globální preference */
    private int [] globalPref = null;
    
    /** Konstruktor. Konfigurační soubor bude "konfig.cfg" */
    public Config() throws TimetableException {
        this("konfig.cfg");
    }
    
    /** Konstruktor. 
     * @param konfigurační soubor
     */
    public Config(String file) throws TimetableException {
        FileInputStream fis = null;
        this.file=file;
        try {
            fis = new FileInputStream(file);
            BufferedReader br = new BufferedReader( new InputStreamReader(fis));
            int line_no=0;
            String line = null;
            while ((line = br.readLine())!=null) 
                if (line.indexOf("#")!=0 && line.length()>0) {
                    line_no++;
                    if (line.indexOf("=")<0) throw new TimetableException("Error in configuration file \""+file+"\" on line "+line_no+"."); 
                    else{
                        configuration.put(line.substring(0,line.indexOf("=")),line.substring(line.indexOf("=")+1));
                    };
                };
            fis.close();
          if (existKey("DEBUG_LOG")) {
            fos = new java.io.FileOutputStream(get("DEBUG_LOG"));
            osw = new java.io.OutputStreamWriter(fos);
          }
          globalPref=new int[getInt(NR_SLOTS)];
          for (int i=0;i<globalPref.length;i++) globalPref[i]=0;
        } catch (Exception e) {
            throw new TimetableException(e.getMessage());
        };
        Loc.addLocalization(this.get("LOC_SOLVER"));
        DAY_OF_WEEK[0]=Loc.get("timetable.config.dayOfWeek.mon");
        DAY_OF_WEEK[1]=Loc.get("timetable.config.dayOfWeek.tue");
        DAY_OF_WEEK[2]=Loc.get("timetable.config.dayOfWeek.wed");
        DAY_OF_WEEK[3]=Loc.get("timetable.config.dayOfWeek.thu");
        DAY_OF_WEEK[4]=Loc.get("timetable.config.dayOfWeek.fri");
        DAY_OF_WEEK[5]=Loc.get("timetable.config.dayOfWeek.sat");
        DAY_OF_WEEK[6]=Loc.get("timetable.config.dayOfWeek.san");
    }
    
    /** Uložení konfiguračního souboru */
    public void save() throws TimetableException {
        FileOutputStream sfos = null;
        try {
            sfos = new FileOutputStream(file);
            OutputStreamWriter sosw = new OutputStreamWriter(sfos);
            for (java.util.Enumeration e=configuration.keys();e.hasMoreElements();) {
                String key = (String)e.nextElement();
                sosw.write(key+"="+get(key)+"\n");
            }
            sosw.flush();sosw.close();
            sfos.close();
        } catch (Exception e) {
            throw new TimetableException(e.getMessage());
        }
    }
      
    /** Získání zapisovače do debug souboru
     */
    public java.io.OutputStreamWriter getLogWriter() {
        return osw;
    }
    
    /** Získání globálních preferencí
     */
    public int [] getGlobalPref() {
        return globalPref;
    }
    
    /** Zápis logovací hlášky do debug souboru. Zápis se provede pouze pokud je logování povoleno (v konfiguraci je DEBUG=1).
     * @param s hláška
     */
    public void log(String s) throws TimetableException {
        try {
            if (existKey("DEBUG_LOG")) osw.write(s+"\n");
            if (getInt("DEBUG")>0) System.out.println(s);
        } catch (Exception e) {
            throw new TimetableException(e.getMessage());
        }
    }
    
    /** Zavře debug výstup
     */
    public void closeLog() throws TimetableException {
        try {
            if (existKey("DEBUG_LOG")) {osw.flush(); osw.close(); fos.close();};
        } catch (Exception e) {
            throw new TimetableException(e.getMessage());
        }
    }
    
    /** Vrátí hodnotu daného klíče (pokud daný klíč v konfiguraci neexistuje, nastane vyjímka TimetableException)
     * @param key klíč
     * @return hodnota jako řetězec
     */
    public String get(String key) throws TimetableException {
        String val=(String)configuration.get(key);
        if (val==null) throw new TimetableException("Key \""+key+"\" not found.");
        return val;
    }
    
    /** Existuje v konfiguraci klíč ?
     * @return true, pokud ano
     */
    public boolean existKey(String key) throws TimetableException {
        return (configuration.get(key)!=null);
    }
    
    /** Vrátí hodnotu daného klíče (pokud daný klíč v konfiguraci neexistuje, nastane vyjímka TimetableException)
     * @param key klíč
     * @return hodnota jako int
     */
    public int getInt(String key) throws TimetableException {
        if (!existKey(key)) throw new TimetableException("Key \""+key+"\" not found.");
        return Integer.parseInt(get(key));
    }

    /** Nastaví daný klíč na zvolenou hodnotu
     * @param key klíč
     * @param val hodnota
     */
    public void set(String key, int val) throws TimetableException {
        set(key,String.valueOf(val));
    }
    
    /** Nastaví daný klíč na zvolenou hodnotu
     * @param key klíč
     * @param val hodnota
     */
    public void set(String key, String val) throws TimetableException {
        configuration.put(key,val);
    }

    /** Vrátí konfiguraci jako řetězec - každý řádek je klíč=hodnota.
     * @return řetězec
     */
    public String toString() {
        StringBuffer s = new StringBuffer();
        boolean first=true;
        for (java.util.Enumeration e=configuration.keys();e.hasMoreElements();) {
            String key = (String)e.nextElement();
            if (!first) s.append('\n');
            s.append(key+"="+configuration.get(key));
            first=false;
        };
        return s.toString();
    }
    
    /** Vrátí den v týdnu pro daný slot
     * @return zkratka dnu
     */
    public String dayOfWeek(int slot) throws TimetableException {
        return DAY_OF_WEEK[slot/(getInt(NR_SLOTS)/getInt(NR_DAYS))];
    }

    /** Zápis konfigurace do streamu */
   private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
       out.writeObject(configuration);
       out.writeObject(globalPref);
   }

   /** Načtení konfigurace ze streamu */
   private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException, TimetableException {
       configuration = (Hashtable) in.readObject();
       globalPref = (int[]) in.readObject();
          if (existKey("DEBUG_LOG")) {
            fos = new java.io.FileOutputStream(get("DEBUG_LOG"));
            osw = new java.io.OutputStreamWriter(fos);
          }
   }

}
