package edu.sc.seis.gee.task;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.apache.log4j.Category;
import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler;
import edu.sc.seis.gee.CommonAccess;
import edu.sc.seis.gee.configurator.ConfigurationException;

/**
 * SequenceTask.java
 *
 *
 * Created: Thu Jun 27 15:42:26 2002
 *
 * @author <a href="mailto:">Philip Crotwell</a>
 * @version
 */

public class SequenceTask extends JPanel implements Task {
    public SequenceTask (){
        setLayout(new BorderLayout());

    }

    public void configure(Map params) throws ConfigurationException {
        this.params = params;

    }

    public void invoke() throws ConfigurationException {
        if (taskList == null) {
            if (params.containsKey("taskSequence")) {
                String taskSeqStr = (String)params.get("taskSequence");
                taskSeqStr = taskSeqStr.trim();
                taskList = new LinkedList();
                String taskId;
                int index;
                TaskAction taskAction;
                logger.debug("Task Seq is "+taskSeqStr);
                while ((index = taskSeqStr.indexOf(' ')) != -1) {
                    taskId = taskSeqStr.substring(0, index);
                    logger.debug("'"+taskId+"'");
                    taskAction =
                        CommonAccess.getCommonAccess().getTaskAction(taskId);
                    taskList.add(taskAction);
                    taskSeqStr = taskSeqStr.substring(index+1).trim();
                } // end of while (taskSeqStr.indexOf(" ") != -1)
                // append last one
                logger.debug(taskSeqStr);
                taskAction =
                    CommonAccess.getCommonAccess().getTaskAction(taskSeqStr);
                taskList.add(taskAction);

            } else {
                throw new ConfigurationException("taskSequence parameter must defined");
            } // end of else


        }

        if ( ! guiInit) {
            guiInit = true;
            if (checkNextPrevNeeded()) {

                JPanel buttonPanel = new JPanel();
                add(buttonPanel, BorderLayout.SOUTH);
                prev = new JButton("<< Prev");
                prev.addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {
                                prevTask();
                            }
                        });
                prev.setEnabled(false);
                buttonPanel.add(prev);

                next = new JButton("Next >>");
                next.addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {
                                nextTask();
                            }
                        });
                next.setEnabled(false);
                buttonPanel.add(next);
            } // end of if (checkNextPrevNeeded)

        } // end of if ( ! guiInit)

        it = taskList.listIterator();
        nextTask();
        checkNextPrev();
    }

    public void destroy(){}

    protected void nextTask() {
        TaskAction taskAction = (TaskAction)it.next();
        while (replaceTask(taskAction) && it.hasNext()) {
            taskAction = (TaskAction)it.next();
        }
    }

    protected void prevTask() {
        TaskAction taskAction = (TaskAction)it.previous();
        while (replaceTask(taskAction) && it.hasPrevious()) {
            taskAction = (TaskAction)it.previous();
        }
    }

    /** @returns true if the task is not JComponent and hence execution
     *  should continue, false otherwise. */
    protected boolean replaceTask(TaskAction taskAction) {
        try {
            if (current == taskAction.getTask()) {
                // must have done a prev after a next
                return true; // cause next in order to be executed
            } // end of if (current == taskAction.getTask())

            if (current != null) {
                remove(current);
                validate();
            } // end of if (current != null)

            boolean isNotJComp = true;
            String displayLoc =
                (String)taskAction.getConfigParam(DISPLAY_LOCATION);
            if (displayLoc == null) {
                displayLoc = FRAME;
            } // end of if (displayLoc == null)
            if ((taskAction.getTask() instanceof JComponent ||
                     taskAction.getTask() instanceof GUITask ) &&
                ! displayLoc.equals(NONE) && ! displayLoc.equals(MAIN)) {

                isNotJComp = false;
                if (taskAction.getTask() instanceof GUITask) {
                    current = ((GUITask)taskAction.getTask()).getGUI();
                } else {
                    current = (JComponent)taskAction.getTask();
                }
                java.awt.Container otherParent;
                if ((otherParent = current.getParent()) != null) {
                    otherParent.remove(current);

                    // check for current inside another sequence
                    while (otherParent != null &&
                           ! (otherParent instanceof SequenceTask)) {
                        otherParent = otherParent.getParent();
                    }
                    if (otherParent != null && otherParent instanceof SequenceTask) {
                        ((SequenceTask)otherParent).getTaskAction().destroyJFrame();
                    } // end of if (otherParent != null)


                } // end of if (current.getParent() != null)
                taskAction.destroyJFrame();

                add(current, BorderLayout.CENTER);
            }

            if ( displayLoc.equals(MAIN )) {
                taskAction.actionPerformed(new ActionEvent(this,
                                                           ActionEvent.ACTION_FIRST,
                                                           "Sequence Task"));
            } else {
                taskAction.getTask().invoke();
            } // end of else

            validate();
            repaint();
            checkNextPrev();
            return isNotJComp;
        } catch (Exception e) {
            GlobalExceptionHandler.handle(e);
            return false;
        } // end of try-catch
    }

    protected boolean checkNextPrevNeeded() throws ConfigurationException {
        Iterator checkIter = taskList.iterator();
        int numGUI = 0;
        while (checkIter.hasNext()) {
            TaskAction taskAction = (TaskAction)checkIter.next();
            String displayLoc =
                (String)taskAction.getConfigParam(DISPLAY_LOCATION);
            if (displayLoc == null) {
                logger.debug("displayLoc is null");
                displayLoc = FRAME;
            } // end of if (displayLoc == null)
            if ((taskAction.getTask() instanceof JComponent ||
                     taskAction.getTask() instanceof GUITask ) &&
                ! displayLoc.equals(NONE)) {
                logger.debug("found gui "+taskAction.getName()+" "+displayLoc);
                numGUI++;
            }
            if (numGUI > 1) {
                return true;
            } // end of if (numGUI > 1)

        } // end of while (it.hasNext())
        return false;
    }

    protected void checkNextPrev() {
        if (next == null || prev == null) {
            return;
        } // end of if (next == null || prev == null)

        if (it.hasNext()) {
            next.setEnabled(true);
        } else {
            next.setEnabled(false);
        } // end of else

        if (it.hasPrevious()) {
            prev.setEnabled(true);
        } else {
            prev.setEnabled(false);
        } // end of else
    }

    public TaskAction getTaskAction() {
        return (TaskAction)params.get(TASK_ACTION);
    }

    Map params;

    List taskList;

    ListIterator it;
    JButton prev = null;
    JButton next = null;
    JComponent current = null;
    boolean guiInit = false;

    static Category logger = Category.getInstance(SequenceTask.class.getName());

}// SequenceTask
