package org.jcon.df.edit;

import org.jcon.df.edit.module.Module;
import org.jcon.df.edit.widget.WidgetSet;
import org.jcon.df.edit.widget.WidgetSetEvent;
import org.jcon.df.edit.widget.WidgetSetView;
import org.jcon.param.Param;
import org.jcon.param.ParamDrivenSupply;
import org.jcon.param.ParamDrivenInfo;
import org.jcon.param.ParamSupplier;
import org.jcon.ui.easylayout.EasyLayout;
import org.jcon.ui.easylayout.EasyLayoutLibraryStd;
import org.jcon.ui.easylayout.EasyLayoutRegistry;
import org.jcon.ui.VisualLib;
import org.jcon.ui.WindowLib;
import org.jcon.ui.PrimeWindow;
import org.jcon.util.DataLib;
import org.jcon.util.GenLib;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

/**
* Presents the VIEW of data by showing reusable components
* such as RowFieldPanel, EditButtonBar, etc. This allows a
* view to be easily composed of workers, each having a
* component.
* <p>
* Note - Call init() before doing anthing else.
*
* @author Jack Harich
*/
public class DataView implements EditListener,
        ActionListener, KeyListener, ParamDrivenSupply,
        WidgetSetView {

//---------- Public Fields -------------------------------
public static String STYLE_LIBRARY = "org.jcon.Standard";

//---------- Private Fields ------------------------------
private EditListener editListener;
private PrimeWindow window = new PrimeWindow();
private EasyLayout  layout;
private Param       param;
private ParamSupplier paramSupplier;
private ComponentConfig componentConfig;
private WidgetSet   widgetSet;
private String      viewName;
private String      editState = "View";
private Vector      modules = new Vector(); // All Module
private String      title;
private boolean     isPrimeView;
private Dimension   windowSize;

private boolean     positioned;
private boolean     windowInited;
private String      windowPosition = "Center";
private String      helpId;     // joshy

//---------- Initialization ------------------------------
static {
    // Register library. Used by some workers
    EasyLayoutLibraryStd library = new EasyLayoutLibraryStd();
    EasyLayoutRegistry.addLibrary(STYLE_LIBRARY, library);
}
public DataView() {
    // Create a layout using the library
    layout = EasyLayoutRegistry.createLayout(STYLE_LIBRARY);
    layout.setTopContainer(window.getMainPanel());
    // Config window
    window.setWindowClosingCommand("CloseWindow");
    window.setActionListener(this);
    window.setKeyListener(this);
    //System.out.println("creating a new DataView: " + this);    
}
//---------- EditListener Implementation -----------------
public void processEditEvent(EditEvent evt) {
    // print(".processEditEvent() - " + evt.getEventTypeString());
    if (evt.getEventType() == EditEvent.EDIT_STATE_CHANGED) {
        // Save to prevent closing if editing
        editState = evt.getEditState();
        refreshTitle();
        return; // Consume <-----<<<
    }
    // Some are also WidgetSetEvents
    if (evt.getEventType() == EditEvent.COMMAND) {
        WidgetSetEvent wsEvent = new WidgetSetEvent(
            WidgetSetEvent.ACTION, viewName);
        wsEvent.setActionCommand(evt.getCommand());
	
	//        print(".processEditEvent()");
	//        print("  widget set = " + widgetSet);
	//        print("  dataview = " + this);
	//        print("  viewname = " + viewName);
        widgetSet.fireEvent(wsEvent);
    }
    if (evt.getEventType() == EditEvent.HELP_REQUESTED) {
        //print(" got event with helpid = " + evt.getHelpId());
    }
    // Set viewName and forward
    if (editListener != null) {
        evt.setViewName(viewName);
        editListener.processEditEvent(evt);
    }
}
//---------- ActionListener Implementation ---------------
public void actionPerformed(ActionEvent evt) {
    //print(".actionPerformed() -" + evt);
    if (evt.getActionCommand().equals("CloseWindow")) {
        if (editListener == null) return;
      
        // Allow close only if in view editState
        if (! editState.equals("View")) return;
        
        EditEvent editEvent = new EditEvent
            (EditEvent.CLOSE, null);
        editEvent.setViewName(viewName);
        editListener.processEditEvent(editEvent);
    }
}
// KeyListner added by Joshua
//---------- KeyListener Implementation ------------------
public void keyTyped(KeyEvent evt) {
}
public void keyPressed(KeyEvent evt) {
    // print(" - keyPressed " + evt);
    if(evt.getKeyCode() == KeyEvent.VK_F1) helpRequested(evt);
}
public void keyReleased(KeyEvent evt) {
}
//---------- ParamDrivenSupply Implementation ------------
public void setParamSupplier(ParamSupplier paramSupplier) {
    this.paramSupplier = paramSupplier;
}
public void setParam(Param param) {
    //print(".setParam() - Entered");
    this.param = param;
}
public Param getParam() {
    if (param == null) {
        paramSupplier.supplyParam(this);
        paramSupplier = null;
    }
    return param;
}
public boolean applyNewParam(Param newParam) {
    window.getMainPanel().removeAll();
    setParam(newParam);
    init();
    return true; // Successful
}
public ParamDrivenInfo getParamDrivenInfo() {
    return null;
}
//---------- WidgetSetView Implementation ----------------
public Window getWindow() {
    return window.getWindow();
}
public String getViewName() {
    return viewName;
}
public void setTitle(String title) {
    this.title = title;
    refreshTitle();
}
//---------- Properties ----------------------------------
public WidgetSet getWidgetSet() {
    return widgetSet;
}
public EasyLayout getEasyLayout() {
    return layout;
}
public void setEditListener(EditListener editListener) {
    this.editListener = editListener;
}
// Return all nested modules
public Vector getAllModules() {
    Vector childModules = new Vector();
    for (int i = 0; i < modules.size(); i++) {
        Module module = (Module)modules.elementAt(i);
        loadChildModules(childModules, module);
    }
    return childModules;
}
// RECURSIVE
private void loadChildModules(Vector childModules, Module module) {
    childModules.addElement(module);
    Vector moduleChildren = module.getChildModules();
    // Recursion stops when no children
    for (int i = 0; i < moduleChildren.size(); i++) {
        Module childModule = (Module)moduleChildren.elementAt(i);
        loadChildModules(childModules, childModule);
    }
}
//----- isPrimeView
public void setPrimeView(boolean isPrimeView) {
    this.isPrimeView = isPrimeView;
}
public boolean isPrimeView() {
    return isPrimeView;
}
//----- viewName
public void setViewName(String viewName) {
    this.viewName = viewName;
}
//----- visible
public void setVisible(boolean visible) {
    if (! positioned) {
        WindowLib.position(window.getWindow(), windowPosition);
        positioned = true;
    }
    window.setVisible(visible);
}
public boolean isVisible() {
    return window.isVisible();
}
//----- title
public String getTitle() {
    return title;
}
//----- windowPosition
public void setWindowPosition(String windowPosition) {
    this.windowPosition = windowPosition;
}
public String getWindowPosition() {
    return windowPosition;
}
//----- windowSize
public void setWindowSize(int width, int height) {
    windowSize = new Dimension(width, height);
}
public Dimension getWindowSize() {
    return windowSize;
}
//---------- Public Methods ------------------------------
// *** Used only by ViewSpeedup as a kludge
public void addModule(Module module) {
    modules.addElement(module);
}
/**
* This must be called after setParam(). It allows a
* delayed initialization.
*/
public void init() {
    widgetSet = null;
    getParam();
    
    // Prepare window
    title = param.getString("Title");
    refreshTitle();

    isPrimeView = param.isTrueDefaultFalse("IsPrimeView");
    window.setFrame(param.isTrueDefaultTrue("IsFrame"));
    window.setModal(param.isTrueDefaultTrue("IsModal"));

    // Note we already have a non-null default
    if (param.hasProperty("WindowPosition")) {
        windowPosition = param.getString("WindowPosition");
    }
    // Add workers with myself as EditListener
    componentConfig = new ComponentConfig(
        layout, param.getParam("Workers"), this);
    componentConfig.config();
    modules = componentConfig.getModules();
    // Window prep
    if (! windowInited) {
        window.initWindow(); // Must be after components added
        windowInited = true;
    }
    if (param.hasProperty("WindowWidth") &&
                    param.hasProperty("WindowHeight")) {
        int width = param.getInt("WindowWidth");
        int height = param.getInt("WindowHeight");
        window.getWindow().setSize(width, height);
    } else {
        window.packWindow();
        //print(".init() - packed window");
    }
    if (param.hasProperty("WindowPosition")) {
        windowPosition = param.getString("WindowPosition");    
    }
    if(param.hasProperty("HelpId")) { // Added by joshy
        helpId = param.getString("HelpId");
        // VisualLib.addKeyListenerToAll(window.getMainPanel(), this);
        //print(".init() - panel = " + window.getMainPanel());
    }
    createWidgetSet();
}    
public void close() {
   try {
        window.dispose();
   } catch(Exception ex) { 
       // Ignore 
   }
}
public void validate() {
    window.getWindow().validate();
}
//---------- Private Methods -----------------------------
private void createWidgetSet() {
    widgetSet = new WidgetSet();
    widgetSet.setWidgetSetView(this);
    //----- Controls
    Vector controls = new Vector();
    // These are controls not in a module
    Vector notCons = componentConfig.getControls();
    for (int i = notCons.size(); --i >= 0; ) {
        controls.addElement(notCons.elementAt(i));
    }
    // These are controls in each module
    Vector allModules = getAllModules();
    for (int i = allModules.size(); --i >= 0; ) {
        Module module = (Module)allModules.elementAt(i);
        Vector cons = module.getControls();
        for (int j = cons.size(); --j >= 0; ) {
            controls.addElement(cons.elementAt(j));
        }
    }
    // Done gathering controls
    widgetSet.setControls(controls);
    //----- Modules        
    widgetSet.setModules(allModules);
}
// Show editState in title
private void refreshTitle() {
    String windowTitle = title;
    if (editState.equals("Add")) {
        windowTitle += " - Adding";
        
    } else if (editState.equals("Change")) {
        windowTitle += " - Changing";
    }
    window.setTitle(windowTitle);
}
// joshy
// *** Why is this protected??? - JH
// *** This method needs an explanation - JH
protected void helpRequested(KeyEvent evt) {
    String id;

    Object o = evt.getSource();
    //  print(".helpRequested \n  event came from " + o + "\n event = " + evt);
    String compid = widgetSet.findHelpId((Component)evt.getSource());
    //  print("help id = " + compid);

    if(compid != null) {
      id = compid;
    } else {
      id = helpId;
    }

    EditEvent event = new EditEvent(EditEvent.HELP_REQUESTED, "??");
    event.setHelpId(id);
    editListener.processEditEvent(event);
    //    print(" my el = " + editListener);
}
//--- Std
private static void print(String text) {
    System.out.println("DataView" + text);
}

} // End class
