package org.jcon.df.edit.task;

import org.jcon.df.Schema;
import org.jcon.param.Param;
import org.jcon.util.GenLib;

/**
 * Expands a meta Param into a full Param for use in a
 * DataEditor. Meta Parameters is a powerful pattern
 * that allows standardized tasks to be defined with a bare
 * minimum of parameters that are expanded into the full
 * parameters needed to accomplish the task.
 *
 * @author Jack Harich
 */
public class Expander {

//---------- Private Fields ------------------------------
private Schema  schema;

//---------- Properties ----------------------------------
/**
 * Sets the schema used to expand the Param. REQUIRED.
 */
public void setSchema(Schema schema) {
    this.schema = schema;
}
//---------- Public Methods ------------------------------
/**
 * Converts the meta param into a full Param by expanding
 * it, using the schema and anticipated meta param formats.
 * Throws an IllegalArgumentException if invalid format.
 */
public Param expandParam(Param metaParam) {
    Param param = new Param();
    String taskType = metaParam.getString("TaskType").intern();

    // Build param
    if (taskType == "EditFields") {
        param = buildEditFields(metaParam);

    } else if (taskType == "BrowseEditFields") {
        param = buildBrowseEditFields(metaParam);

    } else {
        IllegalArgumentException ex = new IllegalArgumentException(
            "Unknown TaskType '" + taskType + "'.");
        GenLib.exception("Expander.expandParam()",
            "Developer muffed up....", ex);
        throw ex;
    }
    return param;
}
//---------- Private Methods -----------------------------
private DataRequestProp createDataRequestProp(Param metaParam) {
    DataRequestProp dataRequestProp = new DataRequestProp();
    dataRequestProp.setSchema(schema);
    dataRequestProp.setMetaParam(metaParam.getParam("DataRequest"));
    return dataRequestProp;
}
private void configOneSource(Param param, DataRequestProp dataRequestProp) {
    String entityName = dataRequestProp.getPrimeEntityName();
    String sourceKey = entityName + "Source.";
    param.put(sourceKey + "Entity", entityName);
    param.put(sourceKey + "DataRequest",
        dataRequestProp.getFullParam());
}
//---------- TaskTypes
private Param buildEditFields(Param metaParam) {
    Param param = new Param();

    DataRequestProp dataRequestProp = createDataRequestProp(metaParam);
    String entityName = dataRequestProp.getPrimeEntityName();
    String sourceID = entityName + "Source";
    String viewName = "View";
    //----- Header - StartMessageName & ParamType not needed
    param.put("ViewNames", viewName);
    param.put("DataSourceIDs", sourceID);
    //----- One Source
    configOneSource(param, dataRequestProp);
    //----- One View
    param.put(viewName + ".IsPrimeView", "true");
    String prefix = (dataRequestProp.isEditable() ? "Edit " : "View ");
    param.put(viewName + ".Title", prefix + entityName + " Table");

    // Note args for EasyLayout
    // This is how we arrange Modules in a window
    String workerKey = viewName + ".Workers.";
    param.put(workerKey + "RowFieldPanel", buildRowFieldPanel(
        sourceID, "Default", "EndRow", dataRequestProp));
    param.put(workerKey + "MoveButtonBar", buildMoveButtonBar(
        sourceID, "GapTopBottomLeft", null));
    param.put(workerKey + "EditButtonBar", buildEditButtonBar(
        sourceID, "GapTopBottomRight", "EndRow", metaParam));

    return param;
}
private Param buildBrowseEditFields(Param metaParam) {
    Param param = new Param();

    DataRequestProp dataRequestProp = createDataRequestProp(metaParam);
    String entityName = dataRequestProp.getPrimeEntityName();
    String sourceID = entityName + "Source";
    String browseName = "BrowseView";
    String detailName = "DetailView"; // Used by class BrowseEditFieldsTask
    //----- Header - StartMessageName & ParamType not needed
    param.put("ViewNames", browseName + ", " + detailName);
    param.put("DataSourceIDs", sourceID);
    //----- One Source
    configOneSource(param, dataRequestProp);
    //---------- 2 Views
    String workerKey;
    //----- Browse View
    param.put(browseName + ".IsPrimeView", "true");
    param.put(browseName + ".WindowPosition", "MiddleLeft");
    param.put(browseName + ".Title", "Browse " + entityName + " Table");
    // RowListPanel & EditButtonBar - Add, Change, etc
    workerKey = browseName + ".Workers.";
    param.put(workerKey + "RowListPanel", buildRowListPanel(
        sourceID, "BorderCenter", null, metaParam.getParam("Browse")));

    // Disable window while editing
    Param barParam = buildEditButtonBar(
        sourceID, "GapBorderBottom", null, metaParam);
    barParam.put("DisableWindowWhileEditing", "true");
    param.put(workerKey + "EditButtonBar", barParam);

    //----- Detail View
    param.put(detailName + ".WindowPosition", "ActiveRight");
    String prefix = (dataRequestProp.isEditable() ? "Edit " : "View ");
    param.put(detailName + ".Title", prefix + entityName + " Table");
    // RowFieldPanel & EditButtonBar - Save, Cancel
    workerKey = detailName + ".Workers.";
    param.put(workerKey + "RowFieldPanel", buildRowFieldPanel(
        sourceID, "Default", "EndRow", dataRequestProp));
    param.put(workerKey + "EditButtonBar", buildEditButtonBar(
        sourceID, "Gap", "EndRow", metaParam));

    //print(".buildBrowseEditFields() param: " + param);
    return param;
}
//---------- Modules
private Param buildRowListPanel(String sourceID,
        String style, String addType, Param browseParam) {

    Param param = new Param();
    param.put("IsModule", "true");
    param.put("Type", "RowListPanel");
    param.put("Style", style);
    if (addType != null) param.put("AddType", addType);
    param.put("DataSourceID", sourceID);

    param.put("Browse", browseParam);

    return param;
}
private Param buildRowFieldPanel(String sourceID,
        String style, String addType, DataRequestProp dataRequestProp) {

    Param param = new Param();
    param.put("IsModule", "true");
    param.put("Type", "RowFieldPanel");
    param.put("Style", style);
    if (addType != null) param.put("AddType", addType);
    param.put("DataSourceID", sourceID);

    // NestedContainer
    FieldLayout fieldLayout = new FieldLayout();
    fieldLayout.setSchema(schema);
    fieldLayout.setColumnIDs(dataRequestProp.getPrimeColumnIDs());
    fieldLayout.setDataSourceID(sourceID);
    Param nestedParam = fieldLayout.buildParam();
    param.put("NestedContainer", nestedParam);

    return param;
}
private Param buildMoveButtonBar(String sourceID,
        String style, String addType) {
    Param param = new Param();
    param.put("IsModule", "true");
    param.put("Type", "MoveButtonBar");
    param.put("Style", style);
    if (addType != null) param.put("AddType", addType);
    param.put("DataSourceID", sourceID);
    return param;
}
private Param buildEditButtonBar(String sourceID,
        String style, String addType, Param metaParam) {

    Param param = new Param();
    param.put("IsModule", "true");
    param.put("Type", "EditButtonBar");
    param.put("Style", style);
    if (addType != null) param.put("AddType", addType);

    if (metaParam.hasProperty("ViewOnly")) {
        String viewOnly = metaParam.getString("ViewOnly");
        param.put("ViewOnly", viewOnly);
    }

    param.put("DataSourceID", sourceID);
    return param;
}
//--- Std
private static void print(String text) {
    System.out.println("Expander" + text);
}

} // End class
