package org.jcon.param.edit;


import org.jcon.ba.system.BasketServices;
import org.jcon.ba.system.BeanPriv;
import org.jcon.ba.system.Item;
import org.jcon.param.ParamStore;
import org.jcon.param.Param;
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 java.util.Vector;

/**
 * Manages the editing of Params in a reusable manner.
 * Assumes the Param can save itself, which greatly reduces
 * inter class dependencies.
 *
 * @author Jack Harich
 */
public class EditParamMgr extends MessageSourceStd
    implements BeanPriv, MessageListener {

//---------- Private Fields ------------------------------
private ParamStore   paramStore;
private Vector  views = new Vector(); // View
private EditParamView    autoView = new EditParamView();
private boolean autoToggleOn = false; // Agrees with main menu

private Param   autoDirtyParam;
private Object  autoDirtyGroupID;
private boolean autoDirtyDialog = false;

//---------- Initialization ------------------------------
public EditParamMgr() {
    autoView.setEditParamMgr(this);
    autoView.setAutoView(true);
}
//---------- MessageSourceStd Abstractions ---------------
public Vector getMessageDefs() {
    Vector defs = new Vector();
    MessageDef def;

    def = new MessageDef("ParamApplied", this);
    def.add("GroupID", Object.class, "Identifies item group.");
    def.add("Param", Param.class, "The Param applied.");
    def.add("Success", Boolean.TYPE, "True if apply successful.");
    defs.addElement(def);

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

    return defs;
}
//---------- BeanPriv Implementation ---------------------
public void setBasketServices(BasketServices services) {
    paramStore = services.getParamStore();
    autoView.setParamStore(paramStore);
}
//---------- MessageListener Implementation --------------
public void processMessage(Message message) {
    String name = message.getName();
    //print(".processMessage() - name is " + name);

    if (name == "EditParam") {
        editParam((Param)message.get("Param"),
            message.get("GroupID"), false, (Item)message.get("Item"));

    // We anticipate this will be called if Param is dirty
    // *** Not yet called, a possibility ***
    } else if (name == "CloseParamEditor") {
        closeParamEditor(message);

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

    } else if (name == "ToggleAutoEditParam") {
        toggleAutoEditParam(message.isTrue("ToggleOn"));

    } else if (name == "ItemSelected") {
        itemSelected((Param)message.get("Param"),
            message.get("GroupID"), (Item)message.get("Item"));
    }
}
public String[] loadMessageInterests() {
    return new String[] {"EditParam", "CloseParamEditor",
        "GroupClosed", "ToggleAutoEditParam", "ItemSelected"};
}
//---------- Private Methods -----------------------------
private void paramGroupClosed(Object groupID) {
    // Close all views with this groupID
    Vector closeViews = new Vector();
    for (int i = 0; i < views.size(); i++) {
        EditParamView view = (EditParamView)views.elementAt(i);
        if (view.getGroupID() == groupID) closeViews.addElement(view);
    }
    for (int i = 0; i < closeViews.size(); i++) {
        EditParamView view = (EditParamView)closeViews.elementAt(i);
        view.close(); // Ask user if dirty
        views.removeElement(view);
    }
    // autoView
    if (autoView.getGroupID() == groupID) emptyAutoView();
}
private void emptyAutoView() {
    // The view should not allow editing
    autoView.setParam(null);
    autoView.setGroupID(null);
}
//---------- Package Methods -----------------------------
void viewClosed(EditParamView view) {
    if (view == autoView) {
        if (autoDirtyDialog) {
            // An itemSelected occurred & the current auto
            // editor was dirty. That editor is now closed.
            // we can now use it for the new itemSelected.
            autoDirtyDialog = false;
            // ********** Guess on null item
            startEditParam(autoView, autoDirtyParam, autoDirtyGroupID, null);

        } else {
            autoToggleOn = false;
            emptyAutoView();
            messageRouter.fire("AutoEditParamClosed", this);
        }
    } else {
        views.removeElement(view);
    }
}
void fireParamAppliedEvent(EditParamView view, Param param,
        boolean success) {
    Message message = new Message("ParamApplied");
    message.set("GroupID", view.getGroupID());
    message.set("Param", param);
    message.setBoolean("Success", success);
    messageRouter.fire(message, this);
}
//---------- Private Methods -----------------------------
private void itemSelected(Param param, Object groupID, Item item) {
    if (autoToggleOn && param != null) {
        editParam(param, groupID, true, item);
    }
}
private void toggleAutoEditParam(boolean autoToggleOn) {
    this.autoToggleOn = autoToggleOn;
    autoView.setVisible(autoToggleOn);
    if (! autoToggleOn) emptyAutoView();
}
private void editParam(Param param, Object groupID,
               boolean isAuto, Item item) {
    EditParamView view = getViewWithParam(param);
    if (view != null) {
        // Already being edited, non-auto
        view.requestFocus();
        GenLib.beep();

    } else if (autoView.getParam() == param && ! isAuto) {
        // Already being edited, auto
        emptyAutoView();
        newNonAutoEditor(param, groupID, item);

    } else if (isAuto) {
        // Auto editor
        if (autoView.isDirty()) {
            autoDirtyParam = param;
            autoDirtyGroupID = groupID;
            autoDirtyDialog = true;
            autoView.close();
        } else {
            startEditParam(autoView, param, groupID, item);
        }

    } else if (! isAuto) {
        // New non-auto editor
        newNonAutoEditor(param, groupID, item);
    }

}
private void newNonAutoEditor(Param param, Object groupID, Item item) {
    EditParamView newView = new EditParamView();
    views.addElement(newView);
    startEditParam(newView, param, groupID, item);
}
private void startEditParam(EditParamView view, Param param,
             Object groupID, Item item) {
    view.setEditParamMgr(this);
    view.setParamStore(paramStore);
    view.setParam(param);
    if (item != null) view.setContainerServices(
            item.getBasket().getContainerServices());
    view.setGroupID(groupID);
    if (! view.isVisible()) view.setVisible(true);
}
// Does nothing if no view has the message Param
// *** Not yet used ***
private void closeParamEditor(Message message) {
    Param param = (Param)message.get("Param");
    EditParamView view = getViewWithParam(param);
    if (view != null) {
        // Even if view goes asynch to ask user if dirty,
        // we are closing regardless, so okay to remove
        view.close(); // Ask user if dirty
        views.removeElement(view);
    }
}
// Returns null if not found
private EditParamView getViewWithParam(Param param) {
    for (int i = 0; i < views.size(); i++) {
        EditParamView view = (EditParamView)views.elementAt(i);
        if (view.getParam() == param) return view;
    }
    return null;
}
//--- Std
private static void print(String text) {
    System.out.println("EditParamMgr" + text);
}

} // End class
