package org.jcon.ba.edit;

import org.jcon.ba.system.Item;
import org.jcon.inspect.Inspector;
import org.jcon.inspect.InspectorController;
import org.jcon.util.GenLib;
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.WindowLib;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
 * Manages the inspectors, with these features: <BR>
 * - Max of one inspector per item <BR>
 * - Can close all inspectors per group <BR>
 * - Can provide inspectors with clipboard services <BR>
 * - (more as encountered)
 *
 * @author Jack Harich
 */
public class InspectMgr extends MessageSourceStd
      implements MessageListener, InspectorController {

//---------- Private Fields ------------------------------
// Key = Item, Object = Use
private Hashtable uses = new Hashtable();

private MessageChain messageChain = new MessageChain();

private Inspector autoInspector = new Inspector();
private Object    autoInspectorGroupID;
private Item      autoInspectorItem;
private boolean   autoToggleOn = false; // Agrees with main menu

//---------- Initialization ------------------------------
public InspectMgr() {
    initInspector(autoInspector);
    autoInspector.setWindowPosition(WindowLib.UPPER_RIGHT);
}
//---------- MessageSourceStd Abstractions ---------------
public Vector getMessageDefs() {
    Vector defs = new Vector();
    MessageDef def;

    def = new MessageDef("AutoInspectorClosed", this);
    defs.addElement(def);

    return defs;
}
//---------- MessageListener Implementation --------------
public void processMessage(Message message) {
    String name = message.getName();
    //print(".processMessage() - name " + name);

    if (name == "InspectItem") {
        inspectItem((Item)message.get("Item"),
            message.get("GroupID"), false);

    } else if (name == "GroupClosed") {
        groupClosed(message.get("GroupID"));

    } else if (name == "ToggleAutoInspector") {
        toggleAutoInspector(message.isTrue("ToggleOn"));

    } else if (name == "ItemSelected") {
        if (autoToggleOn) inspectItem(
            (Item)message.get("Item"),
            message.get("GroupID"), true);
    }
}
private void initInspector(Inspector inspector) {
    inspector.setController(this);
    inspector.setAutoClose(false);
}
public String[] loadMessageInterests() {
    return new String[] {"InspectItem", "GroupClosed",
        "ToggleAutoInspector", "ItemSelected"};
}
//---------- InspectorController Implementation ----------
public void inspectorClosingRequested(Inspector closingInspector) {

    if (closingInspector == autoInspector) {
        // Is autoInspector
        autoInspector.setVisible(false);
        emptyAutoInspector();
        autoToggleOn = false;
        messageRouter.fire("AutoInspectorClosed", this);

    } else {
        // Is one of our inspectors in use
        closingInspector.close();
        // Remove from uses
        Enumeration enum = uses.elements();
        while (enum.hasMoreElements()) {
            Use use = (Use)enum.nextElement();
            if (use.getInspector() == closingInspector) {
                uses.remove(use.getItem());
                return;
            }
        }
    }
}
public Vector loadSignalChain(Inspector inspector,
                    String eventName, Object instance) {
    Item item = getItemForInstance(inspector, instance);
    Vector chain = messageChain.loadSignalChain(
        eventName, item.getItemSystem(), instance);
    chain.insertElementAt("Signal - " + eventName, 0);
    return chain;
}
//---------- Private Methods -----------------------------
private Item getItemForInstance(Inspector inspector,
            Object instance) {
    if (inspector == autoInspector) return autoInspectorItem;

    Enumeration enum = uses.elements();
    while (enum.hasMoreElements()) {
        Use use = (Use)enum.nextElement();
//print(" checking item " + use.getItem().getInstanceName());
        if (use.getItem().getBeanInstance() == instance) {
            return use.getItem();
        }
    }
print(".getItemForInstance() - not found, returning null");
    return null;
}
private void inspectItem(Item item, Object groupID,
        boolean isAuto) {
    // We only inspect beans, never Baskets
    if (! item.isBeanWrapper()) return;

    Use use = (Use)uses.get(item);
    if (use != null) {
        // Already being inspected, non auto
        use.getInspector().requestFocus();
        GenLib.beep();

    } else if (autoInspectorItem == item && ! isAuto) {
        // Already being inspected, auto
        emptyAutoInspector();
        newNonAutoInspector(item, groupID);
//        autoInspector.requestFocus();
//        GenLib.beep();


    } else if (isAuto) {
        // Auto inspector
        autoInspector.setInstance(item.getBeanInstance(),
            item.getItemName());
        if (! autoInspector.isVisible()) autoInspector.setVisible(true);
        autoInspectorGroupID = groupID;
        autoInspectorItem = item;

    } else if (! isAuto) {
        // New non-auto inspector
        newNonAutoInspector(item, groupID);
    }
}
private void newNonAutoInspector(Item item, Object groupID) {
    Use newUse = new Use(item, groupID);
    Inspector inspector = newUse.getInspector();
    initInspector(inspector);
    uses.put(newUse.getItem(), newUse);
}
private void toggleAutoInspector(boolean autoToggleOn) {
    this.autoToggleOn = autoToggleOn;
    autoInspector.setVisible(autoToggleOn);
    if (! autoToggleOn) emptyAutoInspector();
}
private void groupClosed(Object groupID) {
    // Close all inspectors in group
    Enumeration enum = uses.elements();
    while (enum.hasMoreElements()) {
        Use use = (Use)enum.nextElement();
        if (use.getGroupID() == groupID) {
            use.getInspector().close();
            uses.remove(use.getItem());
        }
    }
    if (autoInspectorGroupID == groupID) emptyAutoInspector();
}
private void emptyAutoInspector() {
    // Replace autoInspector with new empty one
    Inspector oldInspector = autoInspector;
    autoInspector = new Inspector();
    initInspector(autoInspector);
    autoInspector.setBounds(oldInspector.getBounds());
    autoInspector.setVisible(oldInspector.isVisible());
    oldInspector.close();
    autoInspectorGroupID = null;
    autoInspectorItem = null;
}
//--- Std
private static void print(String text) {
    System.out.println("InspectMgr" + text);
}
//========== Inner Classes ===============================
class Use { // One inspector use

private Item item;
private Object groupID;
private Inspector inspector;

Use(Item item, Object groupID) {
    this.item = item;
    this.groupID = groupID;
    // This will automatically show the inspector
    inspector = new Inspector(
            item.getBeanInstance(), item.getItemName());
}
Item getItem() {
    return item;
}
Object getGroupID() {
    return groupID;
}
Inspector getInspector() {
    return inspector;
}

} // End inner class


} // End outer class
