package org.jcon.df.edit;

import org.jcon.util.GenLib;
import org.jcon.df.Schema;
import org.jcon.param.Param;
import java.util.StringTokenizer;
import java.util.Vector;

/**
 * Converts English like commands into a Param that drives
 * a DataEditor. This allows simple, standard edits
 * to be defined with just a simple command. An SQL like
 * syntax is used.
 *
 * Keywords start with @, which eliminates name space
 * collisions with column names. All clauses start with a
 * keyword. Clauses may be in any order. The syntax is:
 *
 *    These clauses are required:
 * @EDIT ColumnID1, ColumnID2 or EntityName.*
 * @FROM EntityName1, EntityName2
 * @IN DatabaseName
 *
 *    These clauses are optional:
 * @WHERE ColumnID relation value AND/OR etc
 * @SORTBY ColumnID1, ColumnID2
 * @USING EditType
 * @TITLE The Edit Title
 *
 *    Options and explaniations:
 * All "words" must be separated by one or more spaces.
 *
 * @EDIT may be @VIEW to just view the data.
 * EditType may be EditFields, BrowseEditFields, etc.
 *    The default is EditFields.
 *
 * @NEW_COLUMN in an @EDIT clause starts a new column,
 * useful for arranging large number of fields. *** future feature
 *
 * ColumnID may be EntityName.ColumnName or ColumnName.
 * If the latter then the first entity name is prepended.
 * EntityName.* adds all columns for that entity.
 *
 * @SORTBY sorts in ascending order. To sort in decending
 * order use @SORT_DECENDING. Mixed sorts are not yet supported.
 *
 * If @TITLE is not supplied the title is "Edit EntityName
 * Table" using the first entity name in @FROM.
 *
 * @author Jack Harich *** TEST - NOT USED, old paths
 */
public class DataEditorCommander {

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

// Command properties
private boolean editable;
private Vector  columnIDs = new Vector();
private Vector  entityNames = new Vector();
private String  dbName;
private String  editType;
private String  title;

//---------- Initialization ------------------------------
public static void main(String args[]) {
    new DataEditorCommander().runUnitTest();
}
//---------- Properties ----------------------------------
public void setSchema(Schema schema) {
    this.schema = schema;
}
//---------- Public Methods ------------------------------
public Param toParam(String command) {
    originalCommand = command.trim();
    // Parse command into properties
    parseCommand();
    // Build param from properties
    Param param = new Param();
    if (editType.equals("EditFields")) {
        buildEditFieldsParam(param);
    } else {
        GenLib.error("DataEditorCommander.toParam()",
            "Unknown editType '" + editType + "'.");
        return null;
    }
    return param;
}
public void runUnitTest() {
    String command = "@EDIT SysUser.* @FROM SysUser @IN atsdr";
    Param param = toParam(command);
    System.out.println("   Command:\n" + command +
        "\n   Yields Param:\n" + param);
}
//---------- Private Methods -----------------------------
private void buildEditFieldsParam(Param param) {
    String entityName = getPrimeEntityName();

    param.put("ViewNames", entityName + "View");
    param.put("DataSourceIDs", entityName + "Source");
    String key;
    //----- Source
    key = entityName + "Source.";
    param.put(key + "Database", dbName);
    param.put(key + "Entity", entityName);
    // Note how adding columnIDs cause a "hasLines:"
    param.put(key + "DataRequest.ColumnIds", columnIDs);
    param.put(key + "DataRequest.Entities", entityName);

    //----- View
    key = entityName + "View.";
    param.put(key + "Title", title);

    String sourceID = entityName + "Source";
    String prefix = entityName + "View.Workers.";
    // RowFieldPanel
    key = prefix + "RowFieldPanel.";
    param.put(key + "Class", "org.jcon.df.edit.RowFieldPanel");
    param.put(key + "Style", "Default");
    param.put(key + "AddType", "EndRow");
    param.put(key + "DataSourceID", sourceID);
    param.put(key + "NestedContainer", createRowFieldPanelParam());
    // MoveButtonBar
    key = prefix + "MoveButtonBar.";
    param.put(key + "Class", "org.jcon.df.edit.MoveButtonBar");
    param.put(key + "Style", "GapTopBottomLeft");
    param.put(key + "DataSourceID", sourceID);
    // EditButtonBar on same row
    key = prefix +"EditButtonBar.";
    param.put(key + "Class", "org.jcon.df.edit.EditButtonBar");
    param.put(key + "Style", "GapTopBottomRight");
    param.put(key + "AddType", "EndRow");
    param.put(key + "DataSourceID", sourceID);
}
// *** Fake for now, use schema/entity later ***
// *********************************************
private Param createRowFieldPanelParam() {
    Param param = new Param();
    // Row 1
    addLabelField(param,"UserID", "UserID");
    addTextField(param, "UserID", "10", "SysUser.UserID");
    // Row 2
    addLabelField(param,"FirstName", "First Name");
    addTextField(param, "FirstName", "20", "SysUser.FirstName");

    return param;
}
private void addLabelField(Param param, String prefix,
        String displayName) {
    String key = prefix + "Label.";
    param.put(key + "Type", "Label");
    param.put(key + "Style", "FieldRight");
    param.put(key + "Text", displayName);
}
private void addTextField(Param param, String prefix,
        String columns, String columnID) {
    String key = prefix + "Field.";
    param.put(key + "Type", "TextField");
    param.put(key + "Style", "FieldLeft");
    param.put(key + "AddType", "EndRow");
    param.put(key + "Columns", columns);
    param.put(key + "ColumnID", columnID);
}
// Set propertes given command
// *** Note that "this and that" is not supported
// for column values yet.
private void parseCommand() {

clearProperties();
String clause = "#InitiallyUnknown#";
StringTokenizer words = new StringTokenizer(
    originalCommand, " ");
while (words.hasMoreTokens()) {
    String word = words.nextToken();
    if (word.startsWith("@")) {
        // Assume new clause. @NEW_COLUMN and such later.
        clause = word.toUpperCase().intern();
        if (clause == "@EDIT") editable = true;
        if (clause == "@VIEW") editable = false;

    } else if (clause == "@EDIT" || clause == "@VIEW") {
        word = removeTrailingComma(word);
        columnIDs.addElement(word);

    } else if (clause == "@FROM") {
        word = removeTrailingComma(word);
        entityNames.addElement(word);

    } else if (clause == "@IN") {
        dbName = word;

    } else if (clause == "@TITLE") {
        title += " " + word;

    // Add more clauses here ***

    } else {
        GenLib.error("DataEditorCommander.parseCommandStack()",
            "Unsupported clause '" + clause + "' with word '" + word + "'.");
    }
}
String primeEntityName = getPrimeEntityName();
// Set title
if (title.equals("")) {
    title = "Edit " + primeEntityName + " Table";
} else {
    title = title.trim(); // Remove first " "
}
// Prepend first entityName to columnIDs with not entityName
for (int i = 0; i < columnIDs.size(); i++) {
    String columnID = (String)columnIDs.elementAt(i);
    if (columnID.indexOf(".") < 0) {
        columnID = primeEntityName + "." + columnID;
        columnIDs.setElementAt(columnID, i);
    }
}

} // End method
private void clearProperties() {
    columnIDs.removeAllElements();
    entityNames.removeAllElements();
    dbName = null;
    editType = "EditFields"; // Default
    title = "";
}
// Removes a trailing comma, if any
private String removeTrailingComma(String word) {
    if (word.endsWith(",")) {
        word = word.substring(0, word.length());
    }
    return word;
}
private String getPrimeEntityName() {
    return (String)entityNames.elementAt(0);
}
//--- Std
private static void print(String text) {
    System.out.println("DataEditorCommander" + text);
}

} // End class
