package org.jcon.ba;

import org.jcon.util.msg.Message;
import org.jcon.util.msg.MessageDef;
import org.jcon.util.msg.MessageListener;
import org.jcon.util.msg.MessageSourceStd;
import org.jcon.ui.*;
import org.jcon.ba.system.*;
import org.jcon.ba.tree.ItemTreeEvent;
import org.jcon.ba.tree.ItemTreeListener;
import java.util.Vector;

/**
 * The MEDIATOR for the Bean Assembler. It coordinates
 * various workers in a loose coupling style, taking full
 * advantage of module architecture. If we develop a
 * stong Module this class will have little to do, since
 * the Module is designed to be the mediator.
 * Note - Now a strong mediator to absorb itemSystemMgr.
 *
 * @author Jack Harich
 */
public class Mediator extends MessageSourceStd implements
    BeanActionStart, BeanPriv, MessageListener,
    ItemTreeListener {

//---------- Private Fields ------------------------------
private Vector commandSourceListeners = new Vector();
private ItemSystemMgr  itemSystemMgr = new ItemSystemMgr();
private BasketServices services;

//---------- MessageSourceStd Abstractions ---------------
public Vector getMessageDefs() {
    Vector defs = new Vector();
    MessageDef def;

    def = new MessageDef("TreeOpened", this);
    def.add("RootClassName", String.class, "The root class name.");
    def.add("RootItem", Item.class, "The root item.");
    def.add("IsBATree", Boolean.TYPE, "True if tree is BA tree.");
    defs.addElement(def);

    return defs;
}
//---------- BeanActionStart Implementation --------------
public void start() {
    // Next line puts a bean in STARTED state
    services.startItem("treeMenuItemList");
    treeCountChanged();
}
//---------- BeanPriv Implementation ---------------------
public void setBasketServices(BasketServices services) {
    this.services = services;
}
//---------- MessageListener Implementation --------------
public void processMessage(Message message) {
    String name = message.getName();
    //print(".processMessage() - name = '" + name + "'");

    if (name == "ExitSystem") {
        System.exit(0);

    } else if (name == "FileOpened") {
        String rootClassName = message.getString("FullName");
        processOpenSystem(rootClassName);

    // This is the commandPrefix in MenuFramePD
    } else if (name == "OpenPriorTree") {
        //String rootClassName = name.substring("OpenPriorTree".length() );
        String rootClassName = message.getString("ItemValue");
        processOpenSystem(rootClassName);

    } else if (name == "OpenBATree") {
        // Open ourself
        Item rootItem = services.getRootItem();
        fireTreeOpened(rootItem, true);

    } else if (name == "AutoConfiguratorClosed") {
        setCommandToggle("ToggleAutoConfigurator", false);

    } else if (name == "AutoInspectorClosed") {
        setCommandToggle("ToggleAutoInspector", false);

    } else if (name == "AutoEditParamClosed") {
        setCommandToggle("ToggleAutoEditParam", false);

    } else {
        // We do not handle all we receive
        //print(".processMessage() - Unhandled messageName " + name);
    }
}
public String[] loadMessageInterests() {
    return new String[] {"ExitSystem", "FileOpened",
        "OpenPriorTree*", "OpenBATree",
        "AutoConfiguratorClosed", "AutoInspectorClosed"};
}
//---------- ItemTreeListener Implementation --------------
public void itemTreeClosed(ItemTreeEvent evt) {
    //print(".itemTreeClosed() - event received");
    // Do nothing if BATree so we don't close ourself
    if (evt.isBATree()) return;

    Item rootItem = evt.getRootItem();
    itemSystemMgr.systemClosed(rootItem.getMarkerClass().getClass().getName());
    treeCountChanged();
}
//---------- Events --------------------------------------
//----- CommandSourceEvent
public void addCommandSourceListener(CommandSourceListener listener) {
    commandSourceListeners.addElement(listener);
}
public void removeCommandSourceListener(CommandSourceListener listener) {
    commandSourceListeners.removeElement(listener);
}
//----- Named Messages
public void addMessageListener(String eventName, MessageListener listener) {
    messageRouter.addListener(eventName, listener);
}
public void removeMessageListener(String eventName, MessageListener listener) {
    messageRouter.removeListener(eventName, listener);
}
//---------- Public Methods ------------------------------

//---------- Private Methods -----------------------------
private synchronized void processOpenSystem(String rootClassName) {
    Item rootItem = itemSystemMgr.openSystem(rootClassName, null);
    if (rootItem != null) fireTreeOpened(rootItem, false);
}
private void fireTreeOpened(Item rootItem, boolean isBATree) {
    //----- Fire TreeOpened
    // Create event
    String rootClassName = rootItem.getMarkerClass().getClass().getName();
    Message message = new Message("TreeOpened");
    message.set("RootClassName", rootClassName);
    message.set("RootItem", rootItem);
    message.setBoolean("IsBATree", isBATree);
    // Send event
    messageRouter.fire(message);
    //----- Do related work
    treeCountChanged();
}
private void treeCountChanged() {
    int newCount = itemSystemMgr.getSystemCount();
    boolean enabled = (newCount > 0 ? true : false);
    enableCommand("CloseAllTrees", enabled);
    enableCommand("SaveAllTrees", enabled);
}
private void enableCommand(String command, boolean enabled) {
    CommandSourceEvent event = new CommandSourceEvent(this, command);
    event.setEnabled(enabled);
    event.makeImmutable();

    sendCommandSourceEvent(event);
}
private void setCommandToggle(String command, boolean toggleOn) {
    CommandSourceEvent event = new CommandSourceEvent(this, command);
    event.setToggleOn(toggleOn);
    event.makeImmutable();

    sendCommandSourceEvent(event);
}
private void sendCommandSourceEvent(CommandSourceEvent evt) {
    Vector list;
    synchronized(this) {
        list = (Vector)commandSourceListeners.clone();
    }
    for (int i = 0; i < list.size(); i++) {
        CommandSourceListener listener =
            (CommandSourceListener)list.elementAt(i);
        listener.commandSourceChanged(evt);
    }
}
//--- Std
private static void print(String text) {
    System.out.println("Mediator" + text);
}

} // End class
