package ch.elexis.ebanking.qr;

import java.lang.reflect.InvocationTargetException;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;

import ch.elexis.core.model.IContact;
import ch.elexis.core.model.format.AddressFormatUtil;
import ch.elexis.ebanking.qr.QRBillDataException.SourceType;
import ch.elexis.ebanking.qr.model.QRBillData;
import ch.rgw.tools.Money;

public class QRBillDataBuilder {
	
	private String headerQRType;
	private String headerVersion;
	private String headerCoding;
	
	private IContact cdtrInfContact;
	
	private Money amount;
	private String amountCurrency;
	
	private IContact ultmtDbtrContact;
	
	private String referenceType;
	
	private String reference;
	
	private String referenceUnstructuredRemark;
	
	private String referenceTrailer;
	
	public QRBillDataBuilder(IContact cdtrInf, Money money, String currency, IContact ultmtDbtr){
		// default header values
		this.headerQRType = "SPC";
		this.headerVersion = "0200";
		this.headerCoding = "1";
		
		cdtrInf(cdtrInf);
		amount(money, currency);
		ultmtDbtr(ultmtDbtr);
		
		// default remark value
		this.referenceType = "NON";
		this.referenceTrailer = "EPD";
	}
	
	public QRBillDataBuilder cdtrInf(IContact contact){
		this.cdtrInfContact = contact;
		return this;
	}
	
	public QRBillDataBuilder amount(Money money, String currency) {
		this.amount = money;
		this.amount.roundTo5();
		this.amountCurrency = currency;
		return this;
	}
	
	public QRBillDataBuilder ultmtDbtr(IContact contact){
		this.ultmtDbtrContact = contact;
		return this;
	}
	
	public QRBillDataBuilder reference(String reference){
		this.reference = reference;
		return this;
	}
	
	public QRBillDataBuilder unstructuredRemark(String remark){
		this.referenceUnstructuredRemark = remark;
		return this;
	}
	
	public QRBillData build() throws QRBillDataException{
		QRBillData ret = new QRBillData();
		
		ret.setHeaderQRType(headerQRType);
		ret.setHeaderVersion(headerVersion);
		ret.setHeaderCoding(headerCoding);
		
		ret.setCdtrInfIBAN(StringUtils.defaultString((String) cdtrInfContact.getExtInfo("IBAN")));
		setAddress(ret, "cdtrInf", cdtrInfContact);
		
		ret.setCcyAmtAmt(amount.getAmountAsString().replaceAll(",", "."));
		ret.setCcyAmtCcy(amountCurrency);
		
		setAddress(ret, "ultmtDbtr", ultmtDbtrContact);

		ret.setRmtInfTp(referenceType);
		ret.setRmtInfRef(reference);
		
		ret.setRmtInfUstrd(StringUtils.defaultString(referenceUnstructuredRemark));
		ret.setRmtInfTrailer(referenceTrailer);
		
		return ret;
	}
	
	private void setAddress(QRBillData qrBillData, String prefix, IContact contact)
		throws QRBillDataException{
		try {
			BeanUtils.setProperty(qrBillData, prefix + "AdrTp", "K");
			
			BeanUtils.setProperty(qrBillData, prefix + "Name",
				AddressFormatUtil.getFullnameWithSalutation(contact).replaceAll("\n", " ").trim());
			
			BeanUtils.setProperty(qrBillData, prefix + "StrtNmOrAdrLine1",
				contact.getStreet().trim());
			
			BeanUtils.setProperty(qrBillData, prefix + "StrtNmOrAdrLine2",
				StringUtils.left(contact.getZip().trim() + " " + contact.getCity().trim(), 16));
			
			BeanUtils.setProperty(qrBillData, prefix + "Ctry",
				StringUtils.left(contact.getCountry().name(), 2));
		} catch (IllegalAccessException | InvocationTargetException e) {
			Throwable cause = e.getCause();
			if (cause != null && cause instanceof QRBillDataException) {
				((QRBillDataException) cause).setContact(contact);
				throw (QRBillDataException) cause;
			} else {
				throw new QRBillDataException(SourceType.UNKNOWN, e.getMessage());
			}
		}
	}
}

@@ -263,16 +263,53 @@
 atUtil;%0A
+import ch.elexis.core.types.Country;%0A
 import c
@@ -361,16 +361,16 @@
 ceType;%0A
-
 import c
@@ -1689,16 +1689,210 @@
 erence;%0A
+%09%09if (StringUtils.isNotBlank(reference)) %7B%0A%09%09%09if (reference.length() == 27) %7B%0A%09%09%09%09this.referenceType = %22QRR%22;%0A%09%09%09%7D else if (reference.length() %3C= 25) %7B%0A%09%09%09%09this.referenceType = %22SCOR%22;%0A%09%09%09%7D%0A%09%09%7D%0A
 %09%09return
@@ -3331,32 +3331,139 @@
 im(), 16));%0A%09%09%09%0A
+%09%09%09Country country = contact.getCountry();%0A%09%09%09if (Country.NDF == country) %7B%0A%09%09%09%09country = Country.CH;%0A%09%09%09%7D%0A
 %09%09%09BeanUtils.set
@@ -3527,31 +3527,22 @@
 t(co
+u
 nt
-act.getCountry().name
+ry.toString
 (), 

set qr bill ref type according to ref length, default country CH