package org.jcon.ba.system;

import org.jcon.param.ParamStore;
import org.jcon.param.ParamStoreResource;
import org.jcon.util.GenLib;
import org.jcon.ui.VisualLib;
import java.util.Hashtable;

/**
 * Manages item systems, including starting a system.
 *
 * @author Jack Harich
 */
public class ItemSystemMgr {

//---------- Private Fields ------------------------------
// Key = markerClassName, Object = ItemSystem
private Hashtable systems = new Hashtable();

private boolean    doRootItemStart   = true;
private ParamStore paramStoreDefault = new ParamStoreResource();

//---------- Initialization ------------------------------
// SET SWING LOOK AND FEEL
static {
    VisualLib.installLookAndFeel();
}
/**
 * Used to start a system. The command argument must be
 * markerClassName. Additional commands, if any, are passed
 * as the "CommandArgs".
 */
public static void main(String args1[]) {
    if (args1.length < 1) {
        print("Syntax: java org.jcon.ba.system.ItemSystemMgr <markerClassName>");
        return;
    }
    String[] args2 = null;
    if (args1.length > 1) {
        args2 = new String[args1.length - 1];
        System.arraycopy(args1, 1, args2, 0, args2.length);
    }
    new ItemSystemMgr().startSystem(args1[0], args2);
}
//---------- Properties ----------------------------------
public int getSystemCount() {
    return systems.size();
}
/**
 * Sets the ParamStore used if none is provided for an
 * ItemSystem. The initial default is ParamStoreResource.
 */
public void setParamStoreDefault(ParamStore paramStoreDefault) {
    this.paramStoreDefault = paramStoreDefault;
}
public ParamStore getParamStoreDefault() {
    return paramStoreDefault;
}
//---------- Public Methods ------------------------------
/**
 * "Opens" a system without starting it. This is useful for
 * editing a system before it's started. Returns the root Item.
 */
public Item openSystem(String markerClassName, String args[]) {
    doRootItemStart = false;
        Item rootItem = startSystem(markerClassName, args);
    doRootItemStart = true;
    return rootItem;
}
/**
 * A convenience method which calls startSystem(
 * String markerClassName, null).
 */
public Item startSystem(Object markerClass) {
    return startSystem(markerClass.getClass().getName());
}
/**
 * A convenience method which calls startSystem(
 * String markerClassName, args).
 */
public Item startSystem(Object markerClass, String args[]) {
    return startSystem(markerClass.getClass().getName(), args);
}
/**
 * A system behaves like a parameter driven class. Each
 * system must have a "root marker class" which is used to
 * relatively find the parameters defining the system.
 *
 * If args is not null the root item's basket properties has
 * the propery "CommandArgs" set to args. This allows command
 * line arguments in a main() to be passed to an item system.
 *
 * Returns root Item or null if failure.
 */
public Item startSystem(String markerClassName, String args[]) {
    //print("ItemSystemMgr.startSystem() - entered");
    if (systems.get(markerClassName) != null) {
        GenLib.helpfulHint("System '" + markerClassName +
             "' is already started.");
        return null;
    }
    try {
        // Create ItemSystem
        ItemSystem system = new
            ItemSystem(markerClassName, this);
        // Start rootItem
        Item rootItem = system.getRootItem();
        if (args != null) {
            rootItem.getBasket().getBasketServices()
                .getPropMap().set("CommandArgs", args);
        }
        // Note use of a flag, a technique to be minimized
        if (doRootItemStart) rootItem.start();
        // Save it
        systems.put(markerClassName, rootItem);
        return rootItem;

    } catch(Exception ex) {
        return null;
    }
}
public synchronized void systemClosed(String markerClassName) {
    systems.remove(markerClassName);
}
//---------- Private Methods -----------------------------
//--- Std
private static void print(String text) {
    System.out.println("ItemSystemMgr" + text);
}

} // End class
