/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed 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 (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
/**
 * 
 */
package lu.tudor.santec.gecamed.prescription.gui.drug.lists.cefip.importer;

import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.List;
import java.util.Stack;

import javax.swing.JProgressBar;

import lu.tudor.santec.gecamed.prescription.ejb.entity.beans.drug.cefip.CefipDrugData;
import lu.tudor.santec.gecamed.prescription.ejb.session.interfaces.drug.lists.cefip.CefipDrugManager;
import lu.tudor.santec.gecamed.prescription.gui.drug.lists.cefip.CefipDrugListModule;

import org.apache.log4j.Logger;

import com.svcon.jdbf.DBFReader;
import com.svcon.jdbf.JDBFException;

/**
 * Imports a CEFIP dbf database file into the GECAMed database
 * 
 * While importing, several storing threads are started that send the generated objects to the application server.
 * The generated objects are pushed into a stack and the store threads pull them out again. If the stack size is 
 * getting to high, the generation-process is paused to let the store threads reduce the stack size. 
 * 
 * 
 * @author martin.heinemann@tudor.lu
 *
 *
 * @version
 * <br>$Log: ImportCefipDrug.java,v $
 * <br>Revision 1.10  2013-12-27 18:09:25  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.9  2013-07-15 06:18:36  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.8  2008-09-25 09:43:06  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.7  2008-01-15 09:58:54  heinemann
 * <br>better documentation
 * <br>
 * <br>Revision 1.6  2007/07/19 14:09:59  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.5  2007/07/03 12:35:29  heinemann
 * <br>system.out removed
 * <br>
 * <br>Revision 1.4  2007/03/02 08:28:39  hermen
 * <br>initial checkin after the merge of PatientModuleRebuild with the main HEAD
 * <br>
 * <br>Revision 1.3.2.1  2006/12/20 13:47:04  heinemann
 * <br>*** empty log message ***
 * <br>
 */
public class ImportCefipDrug {

	/* *******************************************************************
	 *   Class Members
	 */
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(ImportCefipDrug.class.getName());
	
	private Stack<CefipDrugData> cefipStack;

	private DBFReader dbfReader;

	private JProgressBar progressBar;
	
	/*   End of Class Members											  */
	/* ****************************************************************** */
	
	
	
	/* ******************************************************************
	 * Class methods
	 */
	
	/**
	 * 
	 * 
	 * @param dbfReader the DBFReader with the dbf file to read from
	 */
	public ImportCefipDrug(DBFReader dbfReader) {
		/* ====================================================== */
		logger.info("Cefip Drug importer created");
		
		this.dbfReader = dbfReader;
		
		// create a new stack
        this.cefipStack = new Stack<CefipDrugData>();
		/* ====================================================== */
	}

	
	public boolean testIntegrity() {
		/* ====================================================== */
		/*
		 * ---------------------------------------------------------- We
		 * will now test, if this is a valid dbf atc file
		 * ----------------------------------------------------------
		 */
		try {
			/* ------------------------------------------------------ */
			if (!dbfReader.getField(0).getName().equals("NUMNAT")
					|| !dbfReader.getField(1).getName().equals(
							"DATEHIST")
					|| !dbfReader.getField(2).getName().equals("DENOM")
					|| !dbfReader.getField(3).getName().equals("FORMECLAIR"))
				return false;

			/* ------------------------------------------------------ */
		} catch (Exception e) {
			return false;
		}
		return true;
		/* ====================================================== */
	}

	/**
	 * Here it will all begin. Start the import.
	 * 
	 * @param max progressbar max size
	 * @throws JDBFException 
	 */
	public void doImport(JProgressBar progressBar, int count) {
		/* ============================================ */
		logger.info("Starting import of CEFIP DrugDatabase");
		/* ---------------------------------------- */
		this.progressBar = progressBar;
		
		List<DrugStoringThread> storeThreads = new ArrayList<DrugStoringThread>();
		long startTime = System.currentTimeMillis();

		/* ------------------------------------------------------ */
		
		// set the text
		this.progressBar.setMaximum(count);
		progressBar.setValue(0);
		/* ------------------------------------------------------ */
		/*
		 * At first a few Threads are started to write
		 * the entities to the session bean.
		 * When the list is finished, a thread is started to
		 * stop the threads.
		 */
		
		// create the threads
		// and start them
		for (int i = 0; i < 1; i++) {
			/* ------------------------------------------------ */
			DrugStoringThread t = new DrugStoringThread(cefipStack);
			storeThreads.add(t);
			t.start();
			/* ------------------------------------------------ */
		}
		
		/* ------------------------------------------------------ */
		// start reading
		
		Object[] row;
		int a = 0;
		
		try {
			/* ------------------------------------------------------ */
			while (dbfReader.hasNextRecord()) {
				/* ---------------------------------------- */
				// progress
				progressBar.setValue(progressBar.getValue()+a++);
				/* ------------------------------------------------------ */
				// get a row from the database
					row = dbfReader.nextRecord();
				/* ------------------------------------------------------ */
				// Create a CefipDrugData object
				CefipDrugData data = new CefipDrugData();
				/* ------------------------------------------------------ */
				// fill the object
				setObjectData(row, data);
				data.setId(null);
				
				// push the object to the stack
				this.cefipStack.push(data);
	
				/* ------------------------------------------------------ */
				// if the stack has reached a size greater than 20
				// pause the creation of new objects and let the
				// storing threads do their work
				try {
					if (cefipStack.size() > 20)
						Thread.sleep(15);
				} catch (InterruptedException e) {
						logger.warn(e.getLocalizedMessage());
				}
				/* ------------------------------------------------------ */
			}
			/* ------------------------------------------------------ */
		} catch (JDBFException e1) {
			// pipe the exception to the next instance
			e1.printStackTrace();
		}
		
		// stop the threads
		for (DrugStoringThread t : storeThreads) {
			t.setOnline(false);
			try {
				t.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("Took " + (System.currentTimeMillis()-startTime) + "ms");
		
		/* ---------------------------------------- */
	}

	/* ============================================ */

	
	/**
	 * Fill the object with data
	 * 
	 * @param row
	 */

	private void setObjectData(Object[] row, CefipDrugData data) {
		/* ====================================================== */
		// this can get some kind of weird
		data.setNumnat(((String) row[0]).trim());
	    data.setDatehist(((String) row[1]).trim());
		data.setDenom(((String) row[2]).trim());
		data.setFormeclair(((String) row[3]).trim());
		data.setDosageq1(((String) row[4]).trim());
		data.setDosageu1(((String) row[5]).trim());
		data.setDosageqp1(((String) row[6]).trim());
		data.setDosageup1(((String) row[7]).trim());
		data.setDosageq2(((String) row[8]).trim());
		data.setDosageu2(((String) row[9]).trim());
		data.setDosageqp2(((String) row[10]).trim());
		data.setDosageup2(((String) row[11]).trim());
		data.setPiece(((String) row[12]).trim());
		data.setLarg(((String) row[13]).trim());
		data.setLongu(((String) row[14]).trim());
		data.setPoids(((String) row[15]).trim());
		data.setVolume(((String) row[16]).trim());
		data.setCondition(((String) row[17]).trim());
		data.setPresent(((String) row[18]).trim());
		data.setPresenta(((String) row[19]).trim());
		data.setEmballage(((String) row[20]).trim());
		data.setVoieadmis1(((String) row[21]).trim());
		data.setVoieadmis2(((String) row[22]).trim());
		data.setVoieadmis3(((String) row[23]).trim());
		data.setVoieadmis4(((String) row[24]).trim());
		data.setCodeatc1(((String) row[25]).trim());
		data.setCodeatc2(((String) row[26]).trim());
		data.setCodeatc3(((String) row[27]).trim());
		data.setCodeatc4(((String) row[28]).trim());
		data.setClassme(((String) row[29]).trim());
		data.setAtcdef(((String) row[30]).trim());
		data.setLimitenbr(((String) row[31]).trim());
		data.setLimitemj(((String) row[32]).trim());
		data.setTdc(((String) row[33]).trim());
		data.setTdcrecons(((String) row[34]).trim());
		data.setDdstma(((String) row[35]).trim());
		data.setDsunites(((String) row[36]).trim());
		data.setReconsnbr(((String) row[37]).trim());
		data.setReconsmjh(((String) row[38]).trim());
		data.setRenouv(((String) row[39]).trim());
		data.setRenouvmois(((String) row[40]).trim());
		data.setPresunique(((String) row[41]).trim());
		data.setCondspec(((String) row[42]).trim());
		data.setNmol(((String) row[43]).trim());
		data.setConddeliv(((String) row[44]).trim());
		data.setTitulaire(((String) row[45]).trim());
		data.setFabricant(((String) row[46]).trim());
		data.setDistribpha(((String) row[47]).trim());
		data.setDistribgro(((String) row[48]).trim());
		data.setCodepamm(((String) row[49]).trim());
		data.setImporte(((String) row[50]).trim());
		data.setPays1(((String) row[51]).trim());
		data.setPays2(((String) row[52]).trim());
		data.setPays3(((String) row[53]).trim());
		data.setPays4(((String) row[54]).trim());
		data.setVigilan1(((String) row[55]).trim());
		data.setVigilan2(((String) row[56]).trim());
		data.setVigilan3(((String) row[57]).trim());
		data.setVigilan4(((String) row[58]).trim());
		data.setProcedure(((String) row[59]).trim());
		data.setProceddate(((String) row[60]).trim());
		data.setCleancenr(((String) row[61]).trim());
		data.setClenouvenr(((String) row[62]).trim());
		data.setDatedeb(((String) row[63]).trim());
		data.setCetat(((String) row[64]).trim());
		data.setDatefin(((String) row[65]).trim());
		data.setDatemem(((String) row[66]).trim());
		data.setEtatmem1(((String) row[67]).trim());
		data.setCetatmem1(((String) row[68]).trim());
		data.setEtatmem2(((String) row[69]).trim());
		data.setCetatmem2(((String) row[70]).trim());
		data.setLufexus(((String) row[71]).trim());
		data.setLufprix(((String) row[72]).trim());
		data.setLufinterv(((String) row[73]).trim());
		data.setLufrefer(((String) row[74]).trim());
		data.setLufb1recom(((String) row[75]).trim());
		data.setEurexusin(((String) row[76]).trim());
		data.setEurprix(((String) row[77]).trim());
		data.setEurinterv(((String) row[78]).trim());
		data.setEurrefer(((String) row[79]).trim());
		data.setEurb1recom(((String) row[80]).trim());
		data.setPaysref(((String) row[81]).trim());
		data.setPaysorig(((String) row[82]).trim());
		data.setTaux(((String) row[83]).trim());
		data.setAbatt(((String) row[84]).trim());
		data.setCategorie(((String) row[85]).trim());
		data.setDateprix(((String) row[86]).trim());
		data.setEtatprix(((String) row[87]).trim());
		data.setApcm(((String) row[88]).trim());
		data.setApcmcond(((String) row[89]).trim());
		data.setApcmdetail(((String) row[90]).trim());
		data.setCefipnum(((String) row[91]).trim());
		data.setCefipcbarr(((String) row[92]).trim());
		data.setCefipdenom(((String) row[93]).trim());
		data.setCefiprespo(((String) row[94]).trim());
		data.setCefprixluf(((String) row[95]).trim());
		data.setCefprixeur(((String) row[96]).trim());
		data.setCefpharluf(((String) row[97]).trim());
		data.setCefphareur(((String) row[98]).trim());
		data.setTva(((String) row[99]).trim());
		data.setNbcomp(((String) row[100]).trim());
		data.setComp1(((String) row[101]).trim());
		data.setCp11(((String) row[102]).trim());
		data.setCp12(((String) row[103]).trim());
		data.setCp13(((String) row[104]).trim());
		data.setCp14(((String) row[105]).trim());
		data.setCp15(((String) row[106]).trim());
		data.setComp2(((String) row[107]).trim());
		data.setCp21(((String) row[108]).trim());
		data.setCp22(((String) row[109]).trim());
		data.setCp23(((String) row[110]).trim());
		data.setCp24(((String) row[111]).trim());
		data.setCp25(((String) row[112]).trim());
		data.setComp3(((String) row[113]).trim());
		data.setCp31(((String) row[114]).trim());
		data.setCp32(((String) row[115]).trim());
		data.setCp33(((String) row[116]).trim());
		data.setCp34(((String) row[117]).trim());
		data.setCp35(((String) row[118]).trim());
		data.setComp4(((String) row[119]).trim());
		data.setCp41(((String) row[120]).trim());
		data.setCp42(((String) row[121]).trim());
		data.setCp43(((String) row[122]).trim());
		data.setCp44(((String) row[123]).trim());
		data.setCp45(((String) row[124]).trim());
		data.setComp5(((String) row[125]).trim());
		data.setCp51(((String) row[126]).trim());
		data.setCp52(((String) row[127]).trim());
		data.setCp53(((String) row[128]).trim());
		data.setCp54(((String) row[129]).trim());
		data.setCp55(((String) row[130]).trim());
		data.setComp6(((String) row[131]).trim());
		data.setCp61(((String) row[132]).trim());
		data.setCp62(((String) row[133]).trim());
		data.setCp63(((String) row[134]).trim());
		data.setCp64(((String) row[135]).trim());
		data.setCp65(((String) row[136]).trim());
		data.setComp7(((String) row[137]).trim());
		data.setCp71(((String) row[138]).trim());
		data.setCp72(((String) row[139]).trim());
		data.setCp73(((String) row[140]).trim());
		data.setCp74(((String) row[141]).trim());
		data.setCp75(((String) row[142]).trim());
		data.setComp8(((String) row[143]).trim());
		data.setCp81(((String) row[144]).trim());
		data.setCp82(((String) row[145]).trim());
		data.setCp83(((String) row[146]).trim());
		data.setCp84(((String) row[147]).trim());
		data.setCp85(((String) row[148]).trim());
		data.setComp9(((String) row[149]).trim());
		data.setCp91(((String) row[150]).trim());
		data.setCp92(((String) row[151]).trim());
		data.setCp93(((String) row[152]).trim());
		data.setCp94(((String) row[153]).trim());
		data.setCp95(((String) row[154]).trim());
		data.setComp10(((String) row[155]).trim());
		data.setCp101(((String) row[156]).trim());
		data.setCp102(((String) row[157]).trim());
		data.setCp103(((String) row[158]).trim());
		data.setCp104(((String) row[159]).trim());
		data.setCp105(((String) row[160]).trim());
		data.setDenominati(((String) row[161]).trim());

		/* ====================================================== */
	}
	
	
	
	
	/* ******************************************************************************** 
	 * 
	 * Additional Classes
	 * 
	 * */
	
	
	/**
	 * @author martin.heinemann@tudor.lu
	 * 
	 * 
	 * @version <br>
	 *          $Log: ImportCefipDrug.java,v $
	 *          Revision 1.10  2013-12-27 18:09:25  donak
	 *          Cleanup of imports
	 *
	 *          Revision 1.9  2013-07-15 06:18:36  ferring
	 *          logging changed
	 *
	 *          Revision 1.8  2008-09-25 09:43:06  heinemann
	 *          fixed copyrights
	 *
	 *          Revision 1.7  2008-01-15 09:58:54  heinemann
	 *          better documentation
	 *
	 *          Revision 1.6  2007/07/19 14:09:59  heinemann
	 *          *** empty log message ***
	 *
	 *          Revision 1.5  2007/07/03 12:35:29  heinemann
	 *          system.out removed
	 *
	 *          Revision 1.4  2007/03/02 08:28:39  hermen
	 *          initial checkin after the merge of PatientModuleRebuild with the main HEAD
	 *
	 *          Revision 1.3.2.1  2006/12/20 13:47:04  heinemann
	 *          *** empty log message ***
	 * <br>
	 *          Revision 1.3 2006/09/13 12:01:00 heinemann <br>
	 *          *** empty log message *** <br>
	 *          <br>
	 *          Revision 1.2 2006/09/11 14:40:25 heinemann <br>
	 *          *** empty log message *** <br>
	 *          <br>
	 *          Revision 1.1 2006/09/07 13:35:38 heinemann <br>
	 *          many changes <br>
	 */
	class DrugStoringThread extends Thread {

		private Stack<CefipDrugData> stack;
		private CefipDrugManager drugManager;

		private boolean online = true;

		public DrugStoringThread(Stack<CefipDrugData> storeStack) {
			/* ============================================== */
			logger.info("Start Drug Save Thread ");
			this.stack = storeStack;
			// obtain an instance of the session bean
			this.drugManager = CefipDrugListModule.getManager();
			/* ============================================== */
		}

		public void run() {
			/* ========================================== */
			while (true) {
				// if offline and stack is empty
				if (!online && stack.empty())
					break;
				// save the entity
				try {
					CefipDrugData d = stack.pop();
					drugManager.saveImportDrug(d);

				} catch (EmptyStackException e) {
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			logger.info("Thread stopped properly");
			/* ========================================== */
		}

		public void setOnline(boolean b) {
			online = b;
		}

	}
}
