package org.jcon.df.edit.module;

import org.jcon.df.edit.EditEvent;
import org.jcon.df.edit.EditListener;
import org.jcon.df.work.Row;
import org.jcon.df.work.RowSetEvent;
import org.jcon.param.Param;
import org.jcon.ui.easylayout.EasyLayout;
import org.jcon.ui.VisualLib;
import org.jcon.ui.WindowLib;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JPanel;

/**
 * Provides a row of buttons for edit commands. In the View
 * state these are Add, Change, Delete, Close. When editing
 * these are Okay, Cancel. ViewOnly is supported.
 *
 * @author Jack Harich
 */
public class EditButtonBar implements Module,
    ActionListener {

//---------- Private Fields ------------------------------
private String           dataSourceID;
private JPanel           buttonBar = new JPanel();
private EditListener controller;
private CardLayout       cardLayout = new CardLayout();
private boolean          useFullNames;
private boolean          includeCloseButton = true;
private boolean          disableWindowWhileEditing;
private boolean          windowEnabled;
private boolean          viewOnly;
private Vector           childModules = new Vector();
private Vector           controls = new Vector();
private String           name;

private JButton           addBtn;
private JButton           changeBtn;
private JButton           deleteBtn;
private JButton           closeBtn;

// Valid states are View, Add, Change
private String           state = "View";

//---------- Initialization ------------------------------
public EditButtonBar() {
    buttonBar.setLayout(cardLayout);
    buttonBar.add("ViewCard", createViewBar());
    buttonBar.add("EditCard", createEditBar());
    setState("View", null);
}
//---------- Module Implementation -----------------------
//----- Name
public void setName(String name) {
    this.name = name;
}
public String getName() {
    return name;
}
//----- Other
// Assume called only once
public void setParam(Param param) {
    dataSourceID = param.getString("DataSourceID");  
    disableWindowWhileEditing = param.isTrueDefaultFalse(
            "DisableWindowWhileEditing");
    viewOnly = param.isTrueDefaultFalse("ViewOnly");
}
public Component getComponent() {
    return buttonBar;
}
public void setEditListener(EditListener controller) {
    //print(".setEditListener() - controller = " + controller);
    this.controller = controller;
}
public void setDataSourceID(String dataSourceID) {
    this.dataSourceID = dataSourceID;
}
public String getDataSourceID() {
    return dataSourceID;
}
public Vector getChildModules() {
    return childModules; // Empty
}
public Vector getControls() {
    return controls; // Empty
}
public void processRowSetEvent(RowSetEvent evt) {
    //print(".processEditEvent() - " + evt);
    switch(evt.getEventType()) {
        case RowSetEvent.EDIT_STATE_CHANGED:
            setState(evt.getEditState(), evt.getCurrentRow());
            break;
        case RowSetEvent.CURRENT_ROW_DATA_CHANGED:
            setState(null, evt.getCurrentRow());
            break;
        case RowSetEvent.CURRENT_ROW_INDEX_CHANGED:
            setState(null, evt.getCurrentRow());
            break;
    }
}
public void requestFocus() {
    // Do nothing, may do something later
}
//---------- ActionListener Implementation ---------------
public void actionPerformed(ActionEvent evt) {
    String command = evt.getActionCommand().intern();
    //print(".actionPerformed() - " + command);
    int eventType = 0;

    if (command == "Add") {
        eventType = EditEvent.BEGIN_ADD;

    } else if (command == "Change") {
        eventType = EditEvent.BEGIN_CHANGE;

    } else if (command == "Delete") {
        eventType = EditEvent.BEGIN_DELETE;

    } else if (command == "Close") {
        eventType = EditEvent.CLOSE;

    } else if (command == "Okay") {
        if (state == "Add") {
            eventType = EditEvent.OKAY_ADD;
        } else {
            eventType = EditEvent.OKAY_CHANGE;
        }

    } else if (command == "Cancel") {
        if (state == "Add") {
            eventType = EditEvent.CANCEL_ADD;
        } else {
            eventType = EditEvent.CANCEL_CHANGE;
        }

    } else {
        print(".actionPerformed() - Unknown command '" + command + "'");
        return;
    }
    if (controller != null && eventType != 0) {
        EditEvent editEvent = new EditEvent(
            eventType, dataSourceID);
        controller.processEditEvent(editEvent);
    }
}
//---------- Properties ----------------------------------
//----- FullNames
/**
 * Sets the FullNames property, which if true will cause
 * full names to be used on the buttons. If false then
 * Abbreviations will be used, allowing smaller buttons.
 * The default is false.
 */
public void setFullNames(boolean useFullNames) {
    this.useFullNames = useFullNames;
}
public boolean isFullNames() {
    return useFullNames;
}
//----- IncludeCloseButton
/**
 * Sets the IncludeCloseButton property, which if true will cause
 * cause the Close button to be included. The default is true.
 */
public void setIncludeCloseButton(boolean includeCloseButton) {
    this.includeCloseButton = includeCloseButton;
}
public boolean isIncludeCloseButton() {
    return includeCloseButton;
}
//----- viewOnly
public boolean isViewOnly() {
    return viewOnly;
}
//---------- Private Methods -----------------------------
private void setState(String newState, Row currentRow) {
    //print(".setState() - state = " + newState);
    if (newState == null) {
        // Only the current row changed
        if (windowEnabled) enableCurrentRowButtons(currentRow);
        return;

    // Which card is showing
    } else if (newState.equals("View")) {
        setWindowEnabled(true);
        cardLayout.show(buttonBar, "ViewCard");
        enableCurrentRowButtons(currentRow);

    } else if (newState.equals("Add") ||
               newState.equals("Change")) {

        if (disableWindowWhileEditing) {
            setWindowEnabled(false);
        } else {
            cardLayout.show(buttonBar, "EditCard");
        }
    } else {
        print(".setState() - Unknown state '" + newState + "'");
        return;
    }
    // Possibly fire event but change state before fire
    boolean changed = (! state.equals(newState) ? true : false);
    state = newState;
    if (changed) {
        EditEvent editEvent = new EditEvent(
            EditEvent.EDIT_STATE_CHANGED, dataSourceID);
        editEvent.setEditState(state);
        controller.processEditEvent(editEvent);
    }
}
private void setWindowEnabled(boolean isEnabled) {
    Window window = WindowLib.findWindow(buttonBar);
    if (window != null) window.setEnabled(isEnabled);

    addBtn.setEnabled(isEnabled);
    changeBtn.setEnabled(isEnabled);
    deleteBtn.setEnabled(isEnabled);
    closeBtn.setEnabled(isEnabled);
    windowEnabled = isEnabled;
}
private void enableCurrentRowButtons(Row currentRow) {
    // Consider viewOnly first
    if (viewOnly) {
        // Disable Add, Change, Delete buttons
        if (addBtn.isEnabled())    addBtn.setEnabled(false);
        if (changeBtn.isEnabled()) changeBtn.setEnabled(false);
        if (deleteBtn.isEnabled()) deleteBtn.setEnabled(false);
        return; // <-----<<<
    }
    // Cannot Change or Delete if no currentRow
    if (currentRow == null) {
        if (changeBtn.isEnabled()) changeBtn.setEnabled(false);
        if (deleteBtn.isEnabled()) deleteBtn.setEnabled(false);
    } else {
        if (! changeBtn.isEnabled()) changeBtn.setEnabled(true);
        if (! deleteBtn.isEnabled()) deleteBtn.setEnabled(true);
    }
}
private Panel createViewBar() {
    Panel bar = new Panel();
    bar.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
    closeBtn = createButton("Close", "Close", null);

    if (useFullNames) {
        addBtn = createButton("Add",    "Add", null);
        changeBtn = createButton("Change", "Change", null);
        deleteBtn = createButton("Delete", "Delete", null);
    } else {
        addBtn = createButton("A",    "Add", "Add");
        changeBtn = createButton("C", "Change", "Change");
        deleteBtn = createButton("D", "Delete", "Delete");
    }
    bar.add(addBtn);
    bar.add(changeBtn);
    bar.add(deleteBtn);
    if (includeCloseButton) bar.add(closeBtn);

    return bar;
}
private Panel createEditBar() {
    Panel bar = new Panel();
    bar.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
    bar.add(createButton("Okay", "Okay", null));
    bar.add(createButton("Cancel", "Cancel", null));
    return bar;
}
private JButton createButton(String text, String command,
        String toolTip) {
    JButton button = VisualLib.createCompactButton(
        text, command, toolTip);    
    button.setActionCommand(command);
    button.addActionListener(this);
    return button;
}
//--- Std
private static void print(String text) {
    System.out.println("EditButtonBar" + text);
}

} // End class
