/*
 * Copyright 
 *   2008 axYus - www.axyus.com
 *   2008 jp.tessier - jean-philippe.tessier@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 General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU 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.plugin.generatorEdmn;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.BoundedRangeModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import org.apache.log4j.Logger;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import fr.gouv.finances.cp.utils.ui.DisplayExceptionDlg;
import fr.gouv.finances.cp.utils.ui.IhmFactory;
import fr.gouv.finances.cp.utils.ui.InfiniteGlassPane;
import fr.gouv.finances.dgfip.xemelios.importers.ImportServiceProvider;

/**
 *
 * @author  jp.tessier
 */
public class ProgressFrame {
	private static final long serialVersionUID = 3977304325938558517L;

	private static Logger logger = Logger.getLogger(ProgressFrame.class);
	private DlgGenEdmn owner=null;
	//private int lastReponse=-1;
	private final static boolean SHOW_CANCEL_BUTTON = true; 
	protected ProgressDlg pg;
	private EdmnImporteurWorker eiw;
	private boolean displayFeedback = true;
	public int[] nbLines={0,0,0,0,0};
	
	public ProgressFrame(DlgGenEdmn owner,EdmnImporteurWorker eiw,File[] tabFiles) {
		super();
		this.owner=owner;
		this.eiw=eiw;
		for(int i=0;i<tabFiles.length;i++){
			try {
				nbLines[i]=getLinesFile(tabFiles[i]);
			} catch (Exception e) {
				nbLines[i]=0;
			}
		}
		
	}

    public void hide() {
        pg.setVisible(false);
    }

	public interface ImmediatlyPaintable {
		public void paintImmediatly();
	}

	public static class PaintableProgress extends JProgressBar implements ImmediatlyPaintable {
		/**
		 * Comment for <code>serialVersionUID</code>
		 */
		private static final long serialVersionUID = 1L;
		public PaintableProgress() { super(); }
		public PaintableProgress(int orient) { super(orient); }
		public PaintableProgress(int min, int max) { super(min, max); }
		public PaintableProgress(int orient, int min, int max) { super(orient, min, max); }
		public PaintableProgress(BoundedRangeModel newModel) { super(newModel); }
		public void paintImmediatly() {
			Runnable code = new Runnable() {
				public void run() {
					paintImmediately(0,0,getWidth(),getHeight());
				}
			};
			if(SwingUtilities.isEventDispatchThread()) code.run();
			else {
				try {
					SwingUtilities.invokeAndWait(code);  
				} catch(Exception ex) {
					logger.error("tu sais ou",ex);
				}
			}
		}
	}
	public void displayProgress() {
		Runnable code = new Runnable() {
			public void run() {
				logger.debug(this.getClass().getName());
				pg = new ProgressDlg(owner,eiw);
				eiw.addPropertyChangeListener(new PropertyChangeListener() {
					public void propertyChange(PropertyChangeEvent evt) {
						String propName = evt.getPropertyName();
						//logger.debug("property "+propName+" changed");
						if("FILE_NAME".equals(propName)) {
							pg.setCurrentFile((String)evt.getNewValue());
						} else if("initialize".equals(propName)) {
							Integer initialize = (Integer)evt.getNewValue();
							pg.setMaximumProgress(initialize.intValue());
						} else if("progress".equals(propName)) {
							Integer progress = (Integer)evt.getNewValue();
							pg.pushCurrentProgress(progress.intValue());
						} else if("currentTerminated".equals(propName)){
							int max = pg.currentProgress.getMaximum();
							int oldProgress = pg.currentProgress.getValue();
							pg.currentProgress.setValue(max);
							pg.globalProgress.setValue((pg.globalProgress.getValue()-oldProgress)+max);
							pg.repaintImmediatly();
						} else if("terminated".equals(propName)) {
							pg.globalProgress.setValue(pg.globalProgress.getMaximum());
							pg.repaintImmediatly();
							owner.setFile_edmn("");
							owner.setFile_index("");
							owner.setBrowseIndexEnabled(false);
							owner.setValidBouttonEnabled(false);
							pg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
							pg.setVisible(false);
						}
					}
				});
				pg.setVisible(true);
			}
		};
		if(SwingUtilities.isEventDispatchThread()) code.run();
		else {
			try { SwingUtilities.invokeAndWait(code); } catch(Throwable t) {}
		}
	}

	public void pushCurrentProgress(final int progress) {
		pg.pushCurrentProgress(progress);
	}
	
	/*public void endCurrentProgress(int position) {
		pg.pushCurrentProgress(nbLines[position]);
	}*/
	
	public void displayMessage(String msg, int msgType) {
		if(shouldDisplayFeedback()) {
			JOptionPane.showMessageDialog(owner,msg,"Génération",msgType==ImportServiceProvider.MSG_TYPE_INFORMATION?JOptionPane.INFORMATION_MESSAGE:JOptionPane.ERROR_MESSAGE);
		}
	}
	public void displayException(Throwable t) {
		new DisplayExceptionDlg((DlgGenEdmn)owner,t);
	}
	public void startLongWait() {
		pg.setUnknownEndded(true);
	}
	public void endLongWait() {
		pg.setUnknownEndded(false);
	}

	public final class ProgressDlg extends JDialog {
		/**
		 * Comment for <code>serialVersionUID</code>
		 */
		private static final long serialVersionUID = 1L;
		public static final String DEFAULT_TEXT = "Traitement de #FILE# en cours : ";
		private boolean shouldContinue = true;
		private EdmnImporteurWorker eiw = null;
		private int nbFilesToImport, nbFilesImported=-1;
		
		PaintableProgress globalProgress, currentProgress;
		JTextField currentFileName;

		public ProgressDlg(DlgGenEdmn owner,EdmnImporteurWorker eiw) {
			super(owner,"Génération en cours...");
			this.eiw=eiw;
			initComponents();
		}
		protected void initComponents() {
			IhmFactory iF = IhmFactory.newInstance();
			FormLayout fl = null;
			if(SHOW_CANCEL_BUTTON) {
				fl = new FormLayout("3dlu,pref,3dlu","3dlu,pref,1dlu,pref,5dlu,pref,1dlu,pref,3dlu,pref,3dlu");
			} else {
				fl = new FormLayout("3dlu,pref,3dlu","3dlu,pref,1dlu,pref,5dlu,pref,1dlu,pref,3dlu");
			}
			CellConstraints cc = new CellConstraints();
			PanelBuilder pb = new PanelBuilder(fl);

			
			currentFileName = new JTextField(30);
			currentFileName.setBackground(getBackground());
			currentFileName.setBorder(BorderFactory.createEmptyBorder());
			currentFileName.setEditable(false);
			currentFileName.setText(DEFAULT_TEXT);

			pb.add(currentFileName,							cc.xy(2,6));
			currentProgress = new PaintableProgress(0,100);
			currentProgress.setStringPainted(true);
			pb.add(currentProgress,							cc.xy(2,8));
			if(SHOW_CANCEL_BUTTON) {
				JButton pbCancel = new JButton("Annuler");
				pbCancel.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent evt) {
						eiw.cancel(true);
					}
				});
				pb.add(pbCancel,								cc.xy(2,10));
			}
			
			pb.add(iF.newLabel("Progression Globale","normal"),	cc.xy(2,2));
			globalProgress = new PaintableProgress(0,100);
			globalProgress.setStringPainted(true);
			int nbLignes = 0;
			for(int i:nbLines) nbLignes+=i;
			globalProgress.setMaximum(nbLignes);
			pb.add(globalProgress,							cc.xy(2,4));
			

			setContentPane(pb.getPanel());
			setResizable(false);
			setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
			pack();
			setLocationRelativeTo(getOwner());
			setVisible(true);
			Graphics g = getGraphics();
			g.setClip(0,0,getWidth(),getHeight());
			paint(g);
			setGlassPane(new InfiniteGlassPane());
		}
		
		public boolean setCurrentFile(String fileName) {
			nbFilesImported++;
			currentFileName.setText(DEFAULT_TEXT.replace("#FILE#",fileName));
			repaintImmediatly();
			return shouldContinue;
		}
		
		public boolean setMaximumProgress(int max) {
			currentProgress.setValue(0);
			currentProgress.setMaximum(max);			
			repaintImmediatly();
			return shouldContinue;
		}
		
		public boolean pushCurrentProgress(int value) {
			currentProgress.setValue(currentProgress.getValue()+value);
			globalProgress.setValue(globalProgress.getValue()+value);
			repaintImmediatly();
			return shouldContinue;
		}
		
		public void repaintImmediatly() {
			currentProgress.paintImmediatly();
			globalProgress.paintImmediatly();
			Graphics g = getGraphics();
			g.setClip(0,0,getWidth(),getHeight());
			if(isLightweight()) {
				paint(g);
			} else {
				update(g);
			}
		}
		
		public void setUnknownEndded(boolean start) {
			getGlassPane().setVisible(start);
		}
	}
	public void setDisplayFeedback(boolean display) {
		displayFeedback = display;
	}
	public boolean shouldDisplayFeedback() { return displayFeedback; }
	
	public int getLinesFile(File f) throws Exception{
		BufferedReader br=null;
		int nbLignes=0;
		try {
			br = new BufferedReader(new FileReader(f));
			String line = br.readLine();

			while (line != null) {
				nbLignes++;
				line = br.readLine();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		if(br!=null)br.close();
		return nbLignes;
	}
}