package info.bukova.isspst.reporting;

import info.bukova.isspst.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JasperRunManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.util.JRProperties;

import org.apache.commons.beanutils.PropertyUtils;

import ar.com.fdvs.dj.core.DynamicJasperHelper;
import ar.com.fdvs.dj.core.layout.ClassicLayoutManager;
import ar.com.fdvs.dj.domain.DynamicReport;
import ar.com.fdvs.dj.domain.builders.ColumnBuilderException;
import ar.com.fdvs.dj.domain.builders.FastReportBuilder;

@SuppressWarnings("deprecation")
public class DynamicGenerator implements Generator {
	
	private ReportDefinition definition;
	private static Map<Class<?>,Class<?>> primitiveMap = new HashMap<Class<?>,Class<?>>();
    static {
    	primitiveMap.put(boolean.class, Boolean.class);
    	primitiveMap.put(byte.class, Byte.class);
    	primitiveMap.put(char.class, Character.class);
    	primitiveMap.put(short.class, Short.class);
    	primitiveMap.put(int.class, Integer.class);
    	primitiveMap.put(long.class, Long.class);
    	primitiveMap.put(float.class, Float.class);
    	primitiveMap.put(double.class, Double.class);
    }
	
	public DynamicGenerator(ReportDefinition definition) {
		this.definition = definition;
	}

	@Override
	public byte[] generate() {
		FastReportBuilder rb = new FastReportBuilder();
		DynamicReport dr;
		
		for (String col : definition.getFieldsToPrint()) {
			Class<?> clazz = colClass(col);
			if (clazz != null) {
				try {
					rb.addColumn(StringUtils.localize(col), col, clazz, 30, false);
				} catch (ColumnBuilderException e) {
					throw new ReportException(e);
				} catch (ClassNotFoundException e) {
					throw new ReportException(e);
				}
			}
		}
		
		rb.setTitle(definition.getReportTitle());
		rb.setUseFullPageWidth(true);
		dr = rb.build();
		
		JRProperties.setProperty("net.sf.jasperreports.default.pdf.encoding", "Cp1250");
		loadLazyData();
		JRDataSource ds = new JRBeanCollectionDataSource(definition.getDataSet());
		try {
			JasperReport report = DynamicJasperHelper.generateJasperReport(dr, new ClassicLayoutManager(), definition.getParams());
			return JasperRunManager.runReportToPdf(report, definition.getParams(), ds);
		} catch (JRException e) {
			throw new ReportException(e);
		}
	}
	
	private Class<?> colClass(String col) {
		List<Object> data = definition.getDataSet();
		if (data != null && data.size() > 0) {
			try {
				Class<?> clazz = PropertyUtils.getPropertyType(data.get(0), col);
				if (clazz.isPrimitive()) {
					clazz = primitiveMap.get(clazz);
				}
				return clazz;
			} catch (IllegalAccessException e) {
				return null;
			} catch (InvocationTargetException e) {
				return null;
			} catch (NoSuchMethodException e) {
				return null;
			} 
		}
		
		return null;
	}
	
	private void loadLazyData() {
		if (definition.getService() == null) {
			return;
		}
		
		for (Object o : definition.getDataSet()) {
			definition.getService().loadLazyData(o);
		}
	}

}
