import java.util.Hashtable;
import java.util.Vector;
import java.awt.Color;
import java.io.*;

/**
 * Classe Init
 * Entierement statique, elle est utilisee pour les manipulations
 * sur les parametres de configuration
 */
public final class Init {
  private static Hashtable table = null;
  private static boolean debug = false;
  public static final char DebMain = '[',
                           FinMain = ']',
                           DebVec = '<',
                           FinVec = '>',
                           SubLevel = ':',
                           Affect = '=',
                           ColorSep = '.';
  private static final String DefaultLevel = "general",
                              DefaultSub = "layout",
                              DebugId = "DebugMode",
                              DebugOk = "Debug";

/**
 * Construit une base de donnee a partir du fichier demande
 * @param Nom du fichier d'initialisation a lire : (name+'.ini')
 */
  public static void LoadINIFile(String name) {
    System.out.print("Loading ini File");
    String level = DefaultLevel, sub=DefaultSub, vec=null, id, value;
    try {

      FileInputStream fis = new FileInputStream(name+".ini");
      DataInputStream dis = new DataInputStream(fis);

      table = new Hashtable();
// Lit toutes les lignes du fichier
      for (String lu=dis.readLine(); lu != null; lu=dis.readLine()) {
        System.out.print(".");
        int Long = lu.length();
	if (Long <2)
	  continue;
        char first=lu.charAt(0);
	if (Character.isSpace(first))
	  continue;
// Il faut traiter la ligne
        int pos;
	switch (first) {
	case DebMain:
	  pos = lu.lastIndexOf(FinMain);
	  level=lu.substring(1, pos==-1?Long-1:pos);
	  sub = DefaultSub;
	  vec = null;
	  continue;
        case DebVec:
	  pos = lu.lastIndexOf(FinVec);
	  vec = lu.substring(1, pos==-1?Long-1:pos);
          continue;
	default:
	  break;
	}
	pos = lu.lastIndexOf(SubLevel);
	if (pos != -1) {
	  sub=lu.substring(0,pos);
	  vec = null;
	  continue;
        }
	if ((pos = lu.lastIndexOf(Affect)) != -1) {
          for (;Character.isSpace(lu.charAt(Long-1)); Long--) /* rien */;
	  sauvegarde( level, sub, vec, lu.substring(0, pos),
	      lu.substring(pos+1, Long));
	}
      }
      System.out.println("SUCCESSFUL!");
    } catch (Exception ex) {
      System.out.println("Erreur lecture fichier initialisation.");
    }
  }

  private static void sauvegarde(String level, String sub, String vec, String id, String value) {
    if (level.equalsIgnoreCase(DefaultLevel) && id.equalsIgnoreCase(DebugId))
      debug=value.equalsIgnoreCase(DebugOk);
    if (vec == null)
      table.put(level.toLowerCase()+sub.toLowerCase()+id.toLowerCase(), value);
    else {
      Vector v = (Vector)table.get(level.toLowerCase()+vec.toLowerCase());
      if (v == null)
        v = new Vector();
      v.addElement(id+Affect+value);
      table.put(level.toLowerCase()+vec.toLowerCase(), v);
    }
  }

/**
 * Recupere une information de configuration
 * @param level Reference sur le tag de niveau
 * @param sub Reference sur le tag de sous-niveau
 * @param id Reference sur l'identificateur du parametre souhaite
 * @return Object:String si c'est un parametre normal, un Vector si le sous niveau fait reference a un tag de liste.
 */
  public static Object get(String level, String sub, String id) {
    return
     (table == null)?null
        :table.get(level.toLowerCase()+sub.toLowerCase()+id.toLowerCase());
  }

/**
 * Redefinition du System.out.println, sert au debugguage
 * N'affiche le texte demande que si le tag Debug (DebugMode=Debug) est
 * positionne dans le sous-niveau Layout du niveau 'level'.
 * @param level Niveau concerne (peut etre le nom de la classe)
 * @param ch texte a afficher si on est en mode debug.
 */
  public static void println(String Level, String ch) {
    if (debug)
      System.out.println(Level+":"+ch);
    else {
      String tmp = (String)get(Level, DefaultSub, DebugId);
      if (tmp != null && tmp.equalsIgnoreCase(DebugOk))
        System.out.println(Level+":"+ch);
    }
  }

/**
 * Calcul un objet Color en fonction d'une chaine de caractere
 * Si c'est (white, black, blue, gray, red, green, pink, yellow)
 * on renvoie une couleur de base de la classe java.awt.Color. Sinon
 * on renvoie une couleur a partir des composantes rouge, verte et bleue
 * contenue dans la chaine.
 * @param name chaine de caractere representant la couleur.
 */
  public static Color getColor(String name) {
    if (name.equalsIgnoreCase("white"))
      return Color.white;
    if (name.equalsIgnoreCase("black"))
      return Color.black;
    if (name.equalsIgnoreCase("blue"))
      return Color.blue;
    if (name.equalsIgnoreCase("gray"))
      return Color.gray;
    if (name.equalsIgnoreCase("red"))
      return Color.red;
    if (name.equalsIgnoreCase("green"))
      return Color.green;
    if (name.equalsIgnoreCase("pink"))
      return Color.pink;
    if (name.equalsIgnoreCase("yellow"))
      return Color.yellow;
    int pos, r=0, g=0, b=0;
    try {
      pos = name.indexOf(ColorSep);
      if (pos == -1)
        return new Color(0, 0, 0);
      String tmp = name.substring(0, pos);
      name = name.substring(pos+1, name.length());
      r = Integer.parseInt(tmp);

      pos = name.indexOf(ColorSep);
      if (pos == -1)
        return new Color(r, 0, 0);
      tmp = name.substring(0, pos);
      name = name.substring(pos+1, name.length());
      g = Integer.parseInt(tmp);

      pos = name.indexOf(ColorSep);
      tmp = name.substring(0, pos==-1?name.length():pos);
      b = Integer.parseInt(tmp);
    } catch (NumberFormatException nfe) {
      System.out.println("Format pour la couleur inconnu");
    }
    return new Color(r, g, b);
  }

}
