/*
 * File:     AbstractResultViewer.java
 * Project:  MPI Linguistic Application
 * Date:     03 April 2006
 *
 * Copyright (C) 2001-2006  Max Planck Institute for Psycholinguistics
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/* This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package mpi.search.viewer;

import mpi.search.model.Match;
import mpi.search.model.Result;
import mpi.search.model.ResultEvent;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JLabel;
import javax.swing.JPanel;


/**
 * $Id: AbstractResultViewer.java,v 1.5 2005/07/19 13:18:36 klasal Exp $
 *
 * @author $Author: klasal $
 * @version $Revision: 1.5 $
 */
public abstract class AbstractResultViewer extends JPanel
    implements ResultViewer {
    /** DOCUMENT ME! */
    protected final Action nextAction;

    /** DOCUMENT ME! */
    protected final Action previousAction;

    /** DOCUMENT ME! */
    protected final JLabel currentLabel;

    /** DOCUMENT ME! */
    protected final JPanel controlPanel;

    /** DOCUMENT ME! */
    protected Result result;

    /** DOCUMENT ME! */
    protected int firstShownMatch = 1;

    /** DOCUMENT ME! */
    protected int lastShownMatch = 0;

    /**
     * Creates a new AbstractResultViewer object.
     */
    public AbstractResultViewer() {
        controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
        currentLabel = new JLabel();
        nextAction = new AbstractAction() {
                    public void actionPerformed(ActionEvent e) {
                        showMatches(getNextInterval());
                    }
                };
        nextAction.putValue(Action.NAME, ">");
        previousAction = new AbstractAction() {
                    public void actionPerformed(ActionEvent e) {
                        showMatches(getPreviousInterval());
                    }
                };
        previousAction.putValue(Action.NAME, "<");
        nextAction.setEnabled(false);
        previousAction.setEnabled(false);
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public JPanel getControlPanel() {
        return controlPanel;
    }

    /**
     * DOCUMENT ME!
     */
    public void reset() {
        nextAction.setEnabled(false);
        previousAction.setEnabled(false);
        controlPanel.setVisible(false);
        firstShownMatch = 1;
        lastShownMatch = 0;
    }

    /**
     * DOCUMENT ME!
     *
     * @param match DOCUMENT ME!
     */
    public abstract void showMatch(Match match);

    /**
     * DOCUMENT ME!
     *
     * @param result DOCUMENT ME!
     */
    public abstract void showResult(Result result);

    /**
     * DOCUMENT ME!
     *
     * @param e DOCUMENT ME!
     */
    public void resultChanged(ResultEvent e) {
        result = (Result) e.getSource();

        if (result.getMatchCount() == 0) {
            reset();
        } else {
            if (e.getType() == ResultEvent.MATCH_ADDED) {
                if ((lastShownMatch - firstShownMatch) < result.getChunkSize()) {
                    showMatch(result.getLastMatch());
                }
            } else if ((e.getType() == ResultEvent.STATUS_CHANGED) &&
                    ((result.getStatus() == Result.COMPLETE) ||
                    (result.getStatus() == Result.INTERRUPTED))) {
                updateButtons();
            }
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @param interval DOCUMENT ME!
     */
    public void showMatches(int[] interval) {
        firstShownMatch = interval[0];
        lastShownMatch = interval[0] - 1;

        for (int i = interval[0]; i <= interval[1]; i++) {
            showMatch(result.getMatch(i));
        }

        updateButtons();
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    protected int[] getNextInterval() {
        if (lastShownMatch < result.getMatchCount()) {
            return new int[] {
                lastShownMatch + 1,
                Math.min((lastShownMatch + result.getChunkSize()),
                    result.getMatchCount())
            };
        }

        return null;
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    protected int[] getPreviousInterval() {
        if (firstShownMatch > 1) {
            return new int[] {
                Math.max(1, firstShownMatch - result.getChunkSize()),
                firstShownMatch - 1
            };
        }

        return null;
    }

    /**
     * DOCUMENT ME!
     *
     * @param interval DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    protected String intervalToString(int[] interval) {
        return (interval != null)
        ? (interval[0] +
        ((interval[0] != interval[1]) ? ("-" + interval[1]) : "")) : null;
    }

    /**
     * DOCUMENT ME!
     */
    protected void updateButtons() {
        previousAction.setEnabled(firstShownMatch != 1);
        nextAction.setEnabled(lastShownMatch < result.getMatchCount());

        currentLabel.setText(firstShownMatch +
            ((firstShownMatch != lastShownMatch) ? ("-" + lastShownMatch) : ""));

        previousAction.putValue(Action.SHORT_DESCRIPTION,
            intervalToString(getPreviousInterval()));
        nextAction.putValue(Action.SHORT_DESCRIPTION,
            intervalToString(getNextInterval()));
    }
}
