package org.jcon.df.edit.control;

import org.jcon.df.Database;
import org.jcon.df.edit.EditEvent;
import org.jcon.df.request.Filter;
import org.jcon.df.request.ReadRowSet;
import org.jcon.df.work.Row;
import org.jcon.param.Param;
import org.jcon.util.DataLib;
import org.jcon.util.GenLib;
import org.jcon.util.minor.KeyedVector;
import java.awt.Component;
import java.awt.Choice;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Hashtable;

/**
 * A Control representing a link to another entity,
 * AKA foreign key. It presents a list of link descriptions
 * and internally provides the MID for the selected
 * description.
 * <p>
 * To show a null value or allow the user to select the
 * equavalent of null, the first choice is "(none)".
 *
 * @author Jack Harich
 */
public class LinkControl extends Control
    implements ItemListener {

//---------- Private Fields ------------------------------
private Choice      choice = new Choice();
private Database    database;
private String      entityName;
private KeyedVector rows = new KeyedVector();

private static final String NONE = "(none)";

//---------- Abstract Implementation ---------------------
public Component getComponent() {
    return (Component)choice;
}
//---------- Superclass Overrides ------------------------
public void init() { // Called after above
    choice.addItemListener(this);
    refresh();
}
public void setEditable(boolean editable) {
    choice.setEnabled(editable);
}
// Value is String MID so select item with that mid
public void setValue(Object value) {
    //print(".setValue() ---- entered, value = '" + value + "'");
    if (value == null) value = "";
    String mid = value.toString().trim();
    if (mid.equals("")) {
        //print(".setValue() - Selecting NONE");
        choice.select(0); // Which is NONE
        return;
    }
    // Note first choice is not in rows so we use "+ 1"
    int index = rows.getIndexForKey(mid) + 1;
    //print(".setValue() - Selecting index " + index);
    choice.select(index);
}
// Returns MID or null if no selection
public Object getValue() {
    // Note first choice is NONE so we use "- 1"
    int index = choice.getSelectedIndex() - 1;
    if (index < 0) {
        //print(".getValue() - null");
        return null;
    } else {
        Row row = (Row)rows.getElementAt(index);
        Object value = row.getValue(entityName + ".MID");
        //print(".getValue() - value = " + value);
        return value;
    }
}
//---------- ItemListener Implementation -----------------
// Called when item selection changes
public void itemStateChanged(ItemEvent evt) {
    // *** not needed, maybe later
}
//---------- Properties ----------------------------------
public void setDatabase(Database database) {
    this.database = database;
}
//---------- Private Methods -----------------------------
/**     myParam data related format:
 * DataSourceID is: Source1
 * EntityName is: SysUser
 * ColumnNames is: LastName, FirstName
 */
private void refresh() {
    //print(".refresh() - param \n" + myParam);

    // Config readRowSet from myParam
    ReadRowSet readRowSet = new ReadRowSet();

    entityName = myParam.getString("EntityName");
    readRowSet.addEntity(entityName);
    readRowSet.addColumnID(entityName + ".MID");

    String sortBy = "";
    String columnNamesLine = myParam.getString("ColumnNames");
    String[] columnNames = DataLib.convertDelimStringToArray(columnNamesLine, ", ");
    String[] columnIDs = new String[columnNames.length];
    int count = columnNames.length;
    for (int i = 0; i < count; i++) {
        String columnID = entityName + "." + columnNames[i];
        columnIDs[i] = columnID;
        readRowSet.addColumnID(columnID);
        sortBy += columnNames[i];
        // Add comma if more
        if (i < count - 1) sortBy += ", ";
    }
    readRowSet.setSortBy(sortBy);

    // Get data
    checkDatabase();
    database.performRequest(readRowSet);
    if (! readRowSet.isSuccessful()) {
        readRowSet.presentFailure();
        return;
    }
    // Read rows, populate rows and choice
    choice.removeAll();
    choice.add(NONE); // <-----<<< First item
    rows.removeAll();
    while (readRowSet.hasMoreRows()) {
        Row row = readRowSet.nextRow();
        Object mid = row.getValue(entityName + ".MID");
        try {
            rows.addElement(row, mid); // <-----<<<
        } catch(Exception ex) {
            GenLib.exception("LinkControl.refresh()",
                "Problem with MID '" + mid + "' in entity '" +
                entityName + "' for row:\n" + row, ex);
            continue;
        }
        addChoiceItem(row, columnIDs);
    }
    readRowSet.close();
}
private void addChoiceItem(Row row, String[] columnIDs) {
    String text = "";
    int count = columnIDs.length;
    for (int i = 0; i < count; i++) {
        String value = row.getString(columnIDs[i]);
        text += value;
        // Add comma if more
        if (i < count - 1 && count > 1) text += ", ";
    }
    choice.add(text);
}
private void checkDatabase() {
    if (database == null) {
        String dataSourceID = myParam.getString("DataSourceID");
        EditEvent evt = new EditEvent(EditEvent
            .ACQUIRE_DATABASE, dataSourceID);
        editListener.processEditEvent(evt);
        database = evt.getDatabase();
    }
}
//--- Std
private static void print(String text) {
    System.out.println("LinkControl" + text);
}

} // End class
