/*
 * Copyright
 *   2007 axYus - www.axyus.com
 *   2007 C.Marchand - christophe.marchand@axyus.com
 *
 * This file is part of XEMELIOS.
 *
 * XEMELIOS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * XEMELIOS 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with XEMELIOS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package fr.gouv.finances.cp.xemelios.ui.resulttable;

import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import org.apache.log4j.Logger;

import fr.gouv.finances.cp.utils.ui.DisplayExceptionDlg;
import fr.gouv.finances.cp.utils.ui.IhmFactory;
import fr.gouv.finances.cp.xemelios.common.config.ElementModel;
import fr.gouv.finances.cp.xemelios.common.config.ListeResultatModel;
import fr.gouv.finances.cp.xemelios.data.DataAccessException;
import fr.gouv.finances.cp.xemelios.data.DataConfigurationException;
import fr.gouv.finances.cp.xemelios.data.DataResultSet;
import fr.gouv.finances.cp.xemelios.ui.ImageResources;
import fr.gouv.finances.cp.xemelios.ui.SearchWindow;
import fr.gouv.finances.cp.xemelios.ui.search.ResultDisplayerThread;

/**
 * A composant that allows user to change page
 * @author chm
 *
 */
public class PageSeeker extends JPanel {
    private static Logger logger = Logger.getLogger(PageSeeker.class);
    /**
     * Comment for <code>serialVersionUID</code>
     */
    private static final long serialVersionUID = 3256725086923863603L;
    private JButton pbFirstPage = null, pbPreviousPage = null, pbNextPage = null, pbLastPage = null;
    private JComboBox cbxPages = null;
    private JLabel label = null;
    private static Dimension buttonDim = new Dimension(20,20);
    private int currentPage = 0, pageCount = 0;
    private SearchWindow searchWindow=null;
    
    public PageSeeker(SearchWindow parent) {
        super();
        this.searchWindow=parent;
        initComponents();
    }
    protected void initComponents() {
        IhmFactory iF = IhmFactory.newInstance();
        FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
        fl.setHgap(0); fl.setVgap(0);
        setLayout(fl);
        pbFirstPage = new JButton(IhmFactory.getIconFromResource(ImageResources.PAGE_FIRST));
        pbFirstPage.setPreferredSize(buttonDim);
        pbFirstPage.setToolTipText("première page");
        add(pbFirstPage);
        
        pbPreviousPage = new JButton(IhmFactory.getIconFromResource(ImageResources.PAGE_PREVIOUS));
        pbPreviousPage.setPreferredSize(buttonDim);
        add(pbPreviousPage);
        pbPreviousPage.setToolTipText("page précédente");
        
        cbxPages = new JComboBox();
        cbxPages.setEditable(false);
        cbxPages.setPreferredSize(new Dimension(50,(int)buttonDim.getHeight()));
        cbxPages.setPrototypeDisplayValue("0000");
        cbxPages.addItem("");
        add(cbxPages);
        
        label = new JLabel("/     ");
        add(label);
        
        pbNextPage = new JButton(IhmFactory.getIconFromResource(ImageResources.PAGE_NEXT));
        pbNextPage.setPreferredSize(buttonDim);
        pbNextPage.setToolTipText("page suivante");
        add(pbNextPage);
        
        pbLastPage = new JButton(IhmFactory.getIconFromResource(ImageResources.PAGE_LAST));
        pbLastPage.setPreferredSize(buttonDim);
        pbLastPage.setToolTipText("dernière page");
        add(pbLastPage);

        reset();
    }
    public void updateData(DataResultSet rs) {
        reset();
        pageCount = rs.getEstimatedPageCount();
        cbxPages.removeAllItems();
        for(int i=1;i<=pageCount;i++) cbxPages.addItem(new Integer(i));
        currentPage = rs.getCurrentPage();
        cbxPages.setSelectedItem(new Integer(currentPage+1));
        StringBuilder sb = new StringBuilder();
        sb.append("/ ").append(pageCount);
        while(sb.length()<6) sb.append(" ");
        label.setText(sb.toString());
        if(rs.hasPreviousPage()) {
            pbPreviousPage.setEnabled(true);
            pbPreviousPage.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    searchWindow.setCursor(new Cursor(Cursor.WAIT_CURSOR));
                    searchWindow.setSearchEnabled(false);
                    searchWindow.getParentFrame().startWaiter();
                    EtatResultTableModel etrm = (EtatResultTableModel)searchWindow.getTable().getModel();
                    DataResultSet rs = etrm.getResultSet();
                    OtherPageSeeker ops = new OtherPageSeeker(rs,rs.getListeResultatModel(),searchWindow.getELementModel(),searchWindow,OtherPageSeeker.PREVIOUS_PAGE);
                    if(SwingUtilities.isEventDispatchThread()) ops.run();
                    else SwingUtilities.invokeLater(ops);
                }
            });
            pbFirstPage.setEnabled(true);
            pbFirstPage.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    searchWindow.setCursor(new Cursor(Cursor.WAIT_CURSOR));
                    searchWindow.setSearchEnabled(false);
                    searchWindow.getParentFrame().startWaiter();
                    EtatResultTableModel etrm = (EtatResultTableModel)searchWindow.getTable().getModel();
                    DataResultSet rs = etrm.getResultSet();
                    OtherPageSeeker ops = new OtherPageSeeker(rs,rs.getListeResultatModel(),searchWindow.getELementModel(),searchWindow,OtherPageSeeker.FIRST_PAGE);
                    if(SwingUtilities.isEventDispatchThread()) ops.run();
                    else SwingUtilities.invokeLater(ops);
                }
            });
        } else {
            pbPreviousPage.setEnabled(false);
            pbFirstPage.setEnabled(false);
        }
        if(rs.hasNextPage()) {
            pbNextPage.setEnabled(true);
            pbNextPage.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    searchWindow.setCursor(new Cursor(Cursor.WAIT_CURSOR));
                    searchWindow.setSearchEnabled(false);
                    searchWindow.getParentFrame().startWaiter();
                    EtatResultTableModel etrm = (EtatResultTableModel)searchWindow.getTable().getModel();
                    DataResultSet rs = etrm.getResultSet();
                    OtherPageSeeker ops = new OtherPageSeeker(rs,rs.getListeResultatModel(),searchWindow.getELementModel(),searchWindow,OtherPageSeeker.NEXT_PAGE);
                    if(SwingUtilities.isEventDispatchThread()) ops.run();
                    else SwingUtilities.invokeLater(ops);
                }
            });
            pbLastPage.setEnabled(true);
            pbLastPage.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    searchWindow.setCursor(new Cursor(Cursor.WAIT_CURSOR));
                    searchWindow.setSearchEnabled(false);
                    searchWindow.getParentFrame().startWaiter();
                    EtatResultTableModel etrm = (EtatResultTableModel)searchWindow.getTable().getModel();
                    DataResultSet rs = etrm.getResultSet();
                    OtherPageSeeker ops = new OtherPageSeeker(rs,rs.getListeResultatModel(),searchWindow.getELementModel(),searchWindow,OtherPageSeeker.LAST_PAGE);
                    if(SwingUtilities.isEventDispatchThread()) ops.run();
                    else SwingUtilities.invokeLater(ops);
                }
            });
        } else {
            pbNextPage.setEnabled(false);
            pbLastPage.setEnabled(false);
        }
        if(pageCount>0) {
	        cbxPages.setEnabled(true);
	        cbxPages.addItemListener(new ItemListener() {
	            public void itemStateChanged(ItemEvent e) {
	                if(e.getStateChange()==ItemEvent.SELECTED) {
		                logger.debug("ITEM SELECTED");
	                    Integer i = (Integer)e.getItem();
	                    searchWindow.setCursor(new Cursor(Cursor.WAIT_CURSOR));
	                    searchWindow.setSearchEnabled(false);
	                    searchWindow.getParentFrame().startWaiter();
	                    EtatResultTableModel etrm = (EtatResultTableModel)searchWindow.getTable().getModel();
	                    DataResultSet rs = etrm.getResultSet();
	                    OtherPageSeeker ops = new OtherPageSeeker(rs,rs.getListeResultatModel(),searchWindow.getELementModel(),searchWindow,OtherPageSeeker.SET_PAGE,i.intValue()-1);
	                    if(SwingUtilities.isEventDispatchThread()) ops.run();
	                    else SwingUtilities.invokeLater(ops);
	                }
	            }
	        });
        } else {
            cbxPages.setEnabled(false);
        }
    }
    public void reset() {
        pbFirstPage.setEnabled(false);
        pbPreviousPage.setEnabled(false);
        pbLastPage.setEnabled(false);
        pbNextPage.setEnabled(false);
        cbxPages.setEnabled(false);
        cbxPages.removeAllItems();
        for(ActionListener al:pbFirstPage.getActionListeners()) pbFirstPage.removeActionListener(al);
        for(ActionListener al:pbPreviousPage.getActionListeners()) pbPreviousPage.removeActionListener(al);
        for(ActionListener al:pbNextPage.getActionListeners()) pbNextPage.removeActionListener(al);
        for(ActionListener al:pbLastPage.getActionListeners()) pbLastPage.removeActionListener(al);
        for(ItemListener il:cbxPages.getItemListeners()) cbxPages.removeItemListener(il);
    }

    private static class OtherPageSeeker implements Runnable {
        public static final int FIRST_PAGE=-2;
        public static final int PREVIOUS_PAGE=-1;
        public static final int SET_PAGE=0;
        public static final int NEXT_PAGE=1;
        public static final int LAST_PAGE=2;
        private DataResultSet rs = null;
        private ListeResultatModel lrm = null;
        private ElementModel em = null;;
        private SearchWindow sw = null;
        int way = 0;
        int page = -1;
        /**
         * 
         * @param rs
         * @param way if positive, indicates next page, if negative, indicates previous page
         */
        public OtherPageSeeker(DataResultSet rs, ListeResultatModel lrm, ElementModel em, SearchWindow sw, int way) {
            super();
            this.rs=rs;
            this.lrm=lrm;
            this.em=em;
            this.sw=sw;
            this.way=way;
        }
        public OtherPageSeeker(DataResultSet rs, ListeResultatModel lrm, ElementModel em, SearchWindow sw, int way, int page) {
            super();
            this.rs=rs;
            this.lrm=lrm;
            this.em=em;
            this.sw=sw;
            this.way=way;
            this.page=page;
        }
        public void run() {
            long start = System.currentTimeMillis();
            sw.getPageSeeker().reset();
            try {
	            switch(way) {
	                case FIRST_PAGE: rs.firstPage(); break;
	                case PREVIOUS_PAGE: rs.previousPage(); break;
	                case NEXT_PAGE: rs.nextPage(); break;
	                case LAST_PAGE: rs.lastPage(); break;
	                case SET_PAGE: rs.setPage(page);
	            }
	            ResultDisplayerThread rdt = new ResultDisplayerThread(rs,lrm,start,em,sw);
	            SwingUtilities.invokeLater(rdt);
            } catch(DataAccessException daEx) {
                new DisplayExceptionDlg(sw.getParentFrame(),daEx);
            } catch(DataConfigurationException dcEx) {
                new DisplayExceptionDlg(sw.getParentFrame(),dcEx);
            }
        }
    }
}
