/*
 * Edifact.java
 * Created on May 26, 2005 
 * Author: 	L�szl� Felf�ldi, Etixpert GmbH
 * mail:	laszlo.felfoldi@etixpert.com		
 */
package com.etixpert.evolution.app.bonus;

import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import com.etixpert.evolution.value.DistributorValue;
import com.etixpert.evolution.value.order.BankAccountValue;

public class Edifact {
	private String strBlz;
	private String strKto;
	
	private static String format(String val, String def) {
		String ret = def + val;
		return ret.substring(ret.length() - def.length());
	}
	
	private static String format(long val, String def) {
		return format("" + val, def);
	}
	
	private static Long toNumber(String src) {
	    try {
	        return new Long(src.replaceAll("[^0-9]", ""));
	    } catch (Exception e) {
	        return null;
	    }
	}
	
	public Edifact(String aBlz, String aKto) {
		strBlz = aBlz;
		strKto = aKto;
	}
	
	public String generate(Date date, Set distributorsWithBonus, Set distributorsWithOpenOrders,
			   Set distributorsWithPayingNotAllowed, Set distributorsWithError, Set distributorsWithoutFirstOrder,
			   Map environment) {
		StringBuffer ret = new StringBuffer();
		
		Calendar     cal = Calendar.getInstance();
		cal.setTime(date);
		
		NumberFormat nf  = NumberFormat.getInstance(Locale.GERMAN);
		nf.setMaximumFractionDigits(2);
		nf.setMinimumFractionDigits(2);
		nf.setGroupingUsed(false);
		
		int year   = cal.get(Calendar.YEAR);
		int month  = cal.get(Calendar.MONTH) + 1;
		int day    = cal.get(Calendar.DAY_OF_MONTH);
		int hour   = cal.get(Calendar.HOUR);
		int minute = cal.get(Calendar.MINUTE);
		int second = cal.get(Calendar.SECOND);
		
		String StrRefNr = "" + year + month + day + hour + minute + second;

		int nSeg = 1;
		  
		ret.append("UNA:+,? '");
		ret.append("UNB+UNOC:3+EVOLUTION GmbH -   .+ATBAA+" + format(year % 100, "00"));
		ret.append(format(month, "00") + format(day, "00") + ":" + format(hour, "00"));
		ret.append(format(minute, "00") + "+XXX20020300102'");
		nSeg += 2;
		  
		ret.append("UNH+" + StrRefNr + "+PAYMUL:D:96A:UN'");
		nSeg++;
		  
		ret.append("BGM+452+" + StrRefNr + "+9'");
		nSeg++;
		  
		ret.append("DTM+137:" + format(year, "0000") + format(month, "00") + format(day, "00") + 
				format(hour, "00") + format(minute, "00") + format(second, "00") + ":204'");
		nSeg++;
		 
		ret.append("FII+MR+" + "+" + strBlz + "'");
		nSeg++;
		  
		ret.append("NAD+MS++EVOLUTION GmbH    .'");
		nSeg++;

		ret.append("LIN+1'");
		nSeg++;
		  
		ret.append("RFF+AEK:" + StrRefNr + "'");
		nSeg++;
		
		ret.append("BUS++DO++TRF'");
		nSeg++;
		
		ret.append("MOA+9:");
		
		StringBuffer strVs2 = new StringBuffer();
		
		strVs2.append("FII+OR+");
		strVs2.append(strKto + "::EVOLUTION GmbH     .+" + strBlz + ":25:137'");
		
		nSeg++;
		String strTxt = "";
		    
		double nSum = 0;
		int    nAnzUms = 1;
		int    nZusTxt = 0;

		StringBuffer strUms1 = new StringBuffer();

		Object[] values = environment.values().toArray();
		Arrays.sort(values, new Comparator() {
		    public int compare(Object o1, Object o2) {
		        DistributorValue dv1 = (DistributorValue) o1;
		        DistributorValue dv2 = (DistributorValue) o2;
		        return dv1.getName().compareTo(dv2.getName());
		    }
		});
		for (int i = 0; i < values.length; i++) {
		    DistributorValue dv = (DistributorValue) values[i];
			// Check the country as the first 2 digits of the id
			if (dv.getId().toString().startsWith("43")) {
			    double netto = Math.round(dv.getNettoBonusToPay() * 100) * 0.01;
				double val =  netto + Math.round(netto * dv.getVATFactor()) * 0.01;
		      	if (val > 0) {
		      		BankAccountValue ba = dv.getBankAccountValue(); 
		      		if (dv.getHasOpenOrders()) {
		      			distributorsWithOpenOrders.add(dv);
		      		} else if (!dv.getTransferBonus()) {
		      			distributorsWithPayingNotAllowed.add(dv);
		      		} else if (dv.getWithoutFirstOrder()) {
		      			distributorsWithoutFirstOrder.add(dv);
		      		} else if (ba == null || toNumber(ba.getBankCode()) == null || toNumber(ba.getAccountNumber()) == null) {
		      			distributorsWithError.add(dv);
		      		} else {
		      			strUms1.append("SEQ++" + nAnzUms + "'");
			      		nSeg++;
	
			      		strUms1.append("MOA+9:" + nf.format(val) + ":EUR'");
			      		nSeg++;
			      		strUms1.append("RFF+PQ:" + "Provision" + format(year, "0000") + format(month, "00") + "'");
			      		nSeg++;
			      		strUms1.append("FII+BF+" + toNumber(ba.getAccountNumber()));
			      		strUms1.append(":" + dv.getName().trim().replaceAll(",", "") + "+" + toNumber(ba.getBankCode()) + "'");
			      		nSeg++;
			      
			      		strUms1.append("PRC+11'FTX+PMD+++");
			      		nSeg++;
			      		strUms1.append("DistributorNr?:" + dv.getId() + "'");
			      		nSeg++;
	
			      		nSum += val;
			      		nAnzUms++;
			      		distributorsWithBonus.add(dv);
		      		}
		      	}
			}
		}
		    
		ret.append(nf.format(nSum) + ":EUR'");
		nSeg++;
		ret.append(strVs2);
		ret.append(strUms1);
		   
		ret.append("CNT+1:" + nf.format(nSum) +  "'");
		nSeg++;
		
		ret.append( "CNT+2:1'");
		nAnzUms--;
		ret.append("CNT+39:" + nAnzUms + "'UNT+" + nSeg + "+" + StrRefNr + "'");
		ret.append("UNZ+1+XXX20020300102'");
  
		return ret.toString();
	}
}
