package org.jcon.util.setting;

import org.jcon.param.Param;
import org.jcon.param.ParamDriven;
import org.jcon.param.ParamDrivenInfo;
import java.util.Hashtable;

/**
 * This class manages a collection of SettingDefs.
 *
 * @author Jack Harich
 */
public class SettingDefMgr implements ParamDriven {

//---------- Private Fields ------------------------------
private Param          myParam;
private SettingTypeMgr settingTypeMgr;
private boolean        initialized;

// Key = name, Object = SettingDef
private Hashtable settingDefs = new Hashtable();

//---------- Initialization ------------------------------
// Roundabout since setSettingTypeMgr called after setParam()
// We have awkward code here, need to improve
private void checkInit() {
    if (! initialized) {
        // Init myself. Support multiple calls.
        settingDefs.clear();
        recurseParam(myParam.getParam("SettingDefs"), null);   
        initialized = true;
    }
}
//---------- ParamDriven Implementation ------------------
public void setParam(Param myParam) {
    this.myParam = myParam;
}
public Param getParam() {
    return myParam; 
}
public boolean applyNewParam(Param newParam) {
    setParam(newParam);
    initialized = false;
    checkInit();
    return true; // Successful
}
public ParamDrivenInfo getParamDrivenInfo() {
    return null;
}
//---------- Properties ----------------------------------
public void setSettingTypeMgr(SettingTypeMgr settingTypeMgr) {
    this.settingTypeMgr = settingTypeMgr;	
}
//---------- Public Methods ------------------------------
public SettingDef getSettingDef(String name) {
    checkInit();
    SettingDef def = (SettingDef)settingDefs.get(name);    
    if (def == null) throw new IllegalArgumentException(
        "SettingDef name '" + name + "' not found in schema.");
    return def;
}
public boolean hasSettingDef(String name) {
    checkInit();
    return (settingDefs.get(name) != null ? true: false);
}
//---------- Private Methods -----------------------------
// Recursively add defs in hierarchial param.
// Stops when param is a def.
// Note name cannot be "Type" <-----<<< (weakness)
private void recurseParam(Param param, String namePath) {
    String[] names = param.getDataKeys();
    for (int i = 0; i < names.length; i++) {
        String name = names[i];
        Param nameParam = param.getParam(name); 
        
        String newNamePath; 
        if (namePath == null) {
            newNamePath = name;
        } else {
            newNamePath = namePath + "." + name;
        }
        if (nameParam.hasProperty("Type")) {
            //print(".recurseParam() - adding type named " + newNamePath);
            // This is a SettingType param, recursion stops
            SettingDef def = new SettingDef(newNamePath, nameParam);
            def.setSettingType(settingTypeMgr
                .getSettingType(def.getType()));
            settingDefs.put(def.getName(), def);
        } else {
            recurseParam(nameParam, newNamePath);
        }
    }	
}//--- Std
private static void print(String text) {
    System.out.println("SettingDefMgr" + text);
}

} // End class
