package org.jcon.df.edit.screen.std;

import org.jcon.ba.system.BeanActionStart;
import org.jcon.ba.system.BasketServices;
import org.jcon.ba.system.BeanPriv;
import org.jcon.df.edit.screen.MasterRegistry;
import org.jcon.df.edit.screen.Screen;
import org.jcon.df.edit.screen.ScreenCommandContext;
import org.jcon.df.edit.screen.ScreenContext;
import org.jcon.df.edit.screen.ScreenLogicRegistry;
import org.jcon.df.edit.screen.ScreenRegistry;
import org.jcon.df.edit.screen.ScreenServiceRegistry;
import org.jcon.df.edit.screen.Sheet;
import org.jcon.df.edit.screen.SheetRegistry;
import org.jcon.df.edit.screen.WidgetDef;
import org.jcon.df.edit.screen.WidgetDefRegistry;
import org.jcon.df.edit.widget.WidgetSet;
import org.jcon.param.Param;
import org.jcon.util.PropMap;
import org.jcon.util.msg.Message;
import org.jcon.util.msg.MessageListener;
import org.jcon.util.msg.MessageRouter;
import org.jcon.util.msg.MessageRouterRegistry;
import java.util.Hashtable;
import java.util.Vector;

/**
* This class defines a collection of registries and
* manages the ScreenContext. It is the hub for the Modular
* Screen Subsystem. See MasterRegistry and ScreenContext
* for some documentation.
*
* @author Jack Harich
*/
public class MasterRegistryStd implements MasterRegistry,
    ScreenContext, BeanPriv, BeanActionStart, MessageListener {

//---------- Private Fields ------------------------------
// Properties
private BasketServices        basketServices;
private SheetRegistry         sheetRegistry;
private ScreenRegistry        screenRegistry;
private WidgetDefRegistry     widgetDefRegistry;
private ScreenLogicRegistry   screenLogicRegistry;
private ScreenServiceRegistry screenServiceRegistry;
// Internal
// Key = WidgetName.SheetName, Object = ""
private Hashtable addedWidgets = new Hashtable();

//---------- MasterRegistry Implementation ----------------
//---------- Properties
public void setSheetRegistry(SheetRegistry registry) {
    sheetRegistry = registry;
}
public void setScreenRegistry(ScreenRegistry registry) {
    screenRegistry = registry;
}
public void setWidgetDefRegistry(WidgetDefRegistry registry) {
    widgetDefRegistry = registry;
}
public void setScreenLogicRegistry(ScreenLogicRegistry registry) {
    screenLogicRegistry = registry;
}
public void setScreenServiceRegistry(ScreenServiceRegistry registry) {
    screenServiceRegistry = registry;
}
//---------- Public Methods
public void startPrimeScreen() {
    //print(".startPrimeScreen() - Entered");
    Screen screen = screenRegistry.getPrimeScreen();
    screen.setScreenContext(this); // <-----<<<
    screen.startScreen(null);    
}
//---------- ScreenContext Implementation ----------------
public Sheet getSheet(String sheetName) {
    if (sheetName == null) sheetName = getDefaultSheetName();
    return sheetRegistry.getSheet(sheetName);
}
public void addWidget(String widgetName, String sheetName) {
    WidgetDef def = widgetDefRegistry.getWidgetDef(widgetName);
    if (sheetName == null) sheetName = getDefaultSheetName();
    getSheet(sheetName).addWidget(def);
    addedWidgets.put(widgetName + "." + sheetName, "");
}
/**
* Also automatically calls addWidget() if a widgetName
* has not been added.
*/
public void setWidgetsVisible(Vector widgetNames,
                    String sheetName, boolean isVisible) {
    // Autoadd feature
    if (sheetName == null) sheetName = getDefaultSheetName();
    for (int i = 0; i < widgetNames.size(); i++) {
        String widgetName = (String)widgetNames.elementAt(i);
        String key = widgetName + "." + sheetName;
        if (! addedWidgets.containsKey(key)) {
            addWidget(widgetName, sheetName);
        }
    }
    // Set visible
    getSheet(sheetName).setWidgetsVisible(widgetNames, isVisible);
}
public WidgetSet getWidgetSet(String sheetName) {
    return getSheet(sheetName).getWidgetSet();
}
public void setSheetVisible(String sheetName, boolean isVisible) {
    getSheet(sheetName).setVisible(isVisible);
}
public void startScreen(String screenName, PropMap propMap) {
    Screen screen = screenRegistry.getScreen(screenName);
    screen.setScreenContext(this); // <-----<<<
    screen.startScreen(propMap);
}
public void setMessageListener(MessageListener listener,
        String sheetName) {
    if (sheetName == null) sheetName = getDefaultSheetName();
    getSheet(sheetName).setMessageListener(listener);
}
/**
* Currently all Messages are forwarded to the
* ScreenServiceRegistry, which fowards them to the services
* interested in the Message.
*/
public void sendMessage(Message message) {
    if (screenServiceRegistry != null) {
        screenServiceRegistry.processMessage(message);
    }
}
public void doCommand(Param cmdParam, ScreenCommandContext cmdContext) {
    screenLogicRegistry.doCommand(cmdParam, cmdContext);
}
public Param getRequestParam(String requestName) {
    return screenLogicRegistry.getRequestParam(requestName);
}
//---------- BeanPriv Implementation ---------------------
public void setBasketServices(BasketServices services) {
    basketServices = services;
}
//----------- BeanActionStart Implementation --------------
public void start() {
    // Get registries, which MUST be in same container
    Vector beans = basketServices.getBeanInstances();
    for (int i = 0; i < beans.size(); i++) {
        Object bean = beans.elementAt(i);
        //print(".start() - Checking bean " + bean.getClass().getName());        
        if (bean instanceof SheetRegistry) {
            setSheetRegistry((SheetRegistry)bean);
            
        } else if (bean instanceof ScreenRegistry) {
            setScreenRegistry((ScreenRegistry)bean);
        
        } else if (bean instanceof WidgetDefRegistry) {
            setWidgetDefRegistry((WidgetDefRegistry)bean);
            
        } else if (bean instanceof ScreenLogicRegistry) {
            setScreenLogicRegistry((ScreenLogicRegistry)bean);          
            
        } else if (bean instanceof ScreenServiceRegistry) {
            setScreenServiceRegistry((ScreenServiceRegistry)bean);
        }
    }
    // Support AutoTest. Remove is so we are not added twice.
    MessageRouter router = MessageRouterRegistry.getSingletonDefaultRouter();
    router.removeListener("DoScreenCommand", this);
    router.addListener("DoScreenCommand", this);
    // Done
    startPrimeScreen();
}
//---------- MessageListener Implementation --------------
/**
* Processes messages named "DoScreenCommand" as part of the
* AutoTest subsystem.
*/
public void processMessage(Message message) {
    String messageName = message.getName();
    //print(".processMessage() - Name = " + messageName);

    if (messageName == "DoScreenCommand") {
        Param cmdParam = (Param)message.get("CommandParam");
        //print(".processMessage() - Before calling doCommand()");
        doCommand(cmdParam, null);

    } else {
        print(".processMessage() - Unknown messageName '" + messageName + "'");
    }
}
public String[] loadMessageInterests() {
    return new String[] {"DoScreenCommand"};
}
//---------- Private Methods -----------------------------
private String getDefaultSheetName() {
    return sheetRegistry.getDefaultSheetName();
}
//--- Std
private static void print(String text) {
    System.out.println("MasterRegistryStd" + text);
}

} // End class
