package com.zt.plat.module.qms.framework.gridreport;

import java.io.Serializable;
import java.util.Map;

import com.zt.plat.module.qms.framework.gridreport.exception.GridReportException;
import gridreport.jni.BinaryObject;
import gridreport.jni.E2IMGOption;
import gridreport.jni.ExportImageType;
import gridreport.jni.ExportOption;
import gridreport.jni.ExportType;
import gridreport.jni.Report;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class GridReport implements Serializable {

    private static final long serialVersionUID = -8308393930858342837L;

    public static final String WR_PREFIX = "_WR_";
        
    private String gridReportOutPath;
    
    public GridReport() {}
    
    public GridReport(String gridReportOutPath) {
        this.gridReportOutPath = gridReportOutPath;
    }

    /**
     * 输出目录
     * @return
     */
    public String getGridReportOutPath() {
        return gridReportOutPath;
    }

    /**
     * 获取报表对象
     * @return
     * @throws Exception
     */
    public Report getReport() throws Exception {
        if (!"amd64".equalsIgnoreCase(System.getProperty("os.arch"))) {
            log.error("锐浪报表SDK不支持当前" + System.getProperty("os.arch") + "平台！");
        }
        Report report = new Report();
        if (report.getNativeHandle() == 0) {
            throw new Exception("Report Create failed.");
        }
        return report;
    }
    
    /**
     * 导出报表二进制数据
     * @param reportTemplate 报表模板json数据
     * @param reportData 报表json数据
     * @param reportParams 报表参数
     * @param type 报表类型
     * @return
     * @throws Exception
     */
    public BinaryObject genReport(String reportTemplate, String reportData, Map<String, String> reportParams, ExportType type) throws Exception {
        Report report = new Report();
        boolean success = report.LoadFromStr(reportTemplate);
        if (!success) {
            log.error("加载报表模板数据失败！");
            throw new GridReportException("加载报表模板数据失败！");
        }
        success = report.LoadDataFromXML(reportData);
        if (!success) {
            log.error("加载报表数据失败！");
            throw new GridReportException("加载报表数据失败！");
        }
        //处理报表参数
        for (Map.Entry<String, String> param : reportParams.entrySet()) {
            if (report.ParameterByName(param.getKey()) != null) {
                report.ParameterByName(param.getKey()).setAsString(param.getValue());
            }
        }
        BinaryObject bo = report.ExportDirectToBinaryObject(type);
        if (bo == null || bo.getNativeHandle() == 0) {
            log.error("导出二进制数据失败！");
            throw new GridReportException("导出二进制数据失败！");
        }
        return bo;
    }
    
    /**
     * 导出报表二进制数据
     * @param reportTemplate 报表模板json数据
     * @param reportData 报表json数据
     * @param reportParams 报表参数
     * @param type 报表类型
     * @param imgType 指定生成的图像数据格式，仅当生成图像数据时需要，可选[png|bmp|jpg|tif]
     * @param imgDpi 指定导出图像的分辨率DPI,默认为96。打印的化需要根据打印机来具体设置
     * @return
     * @throws Exception
     */
    public BinaryObject genReport(String reportTemplate, String reportData, Map<String, String> reportParams, ExportType type, ExportImageType imgType, Integer imgDPI) throws Exception {
    	Report report = new Report();
        boolean success = report.LoadFromStr(reportTemplate);
        if (!success) {
            log.error("加载报表模板数据失败！");
            throw new GridReportException("加载报表模板数据失败！");
        }
        success = report.LoadDataFromXML(reportData);
        if (!success) {
            log.error("加载报表数据失败！");
            throw new GridReportException("加载报表数据失败！");
        }
        //处理报表参数
        for (Map.Entry<String, String> param : reportParams.entrySet()) {
            if (report.ParameterByName(param.getKey()) != null) {
                report.ParameterByName(param.getKey()).setAsString(param.getValue());
            }
        }
        //准备进行数据导出，指定要导出的文件类型。
        //在调用Export方法之前一定要调用本方法，在其后一定要调用UnprepareExport方法。本方法返回的选项对象的接口引用可以用来设定选项值。
        ExportOption exportOption = report.PrepareExport(type);
        if (type.equals(ExportType.IMG)) {//如果为图片格式
        	//获取将本对象转换为导出图像文件选项对象的接口引用。
			E2IMGOption e2imgOption = exportOption.getAsE2IMGOption();
			//设置图片格式
			e2imgOption.setImageType(imgType);
			//所有页产生在一个图像文件中
			e2imgOption.setAllInOne(true);
			e2imgOption.setDPI(imgDPI);
		}
        //执行数据导出
        BinaryObject bo = report.ExportToBinaryObject();
        //数据导出完成之后，进行一些内部释放任务。
        report.UnprepareExport();
        if (bo == null || bo.getNativeHandle() == 0) {
            log.error("导出二进制数据失败！");
            throw new GridReportException("导出二进制数据失败！");
        }
        return bo;
        
	}
    
    /**
     * 生成报表并保存
     * @param reportName 报表名称
     * @param reportTemplate 报表模板json
     * @param reportData 报表数据json
     * @param reportParams 报表参数
     * @param type 报表类型
     * @return 报表保存路径
     * @throws Exception
     */
    public String genReportAndSave(String reportName, String reportTemplate, String reportData, Map<String, String> reportParams, ExportType type) throws Exception {
        Report report = new Report();
        boolean success = report.LoadFromStr(reportTemplate);
        if (!success) {
            log.error("加载报表模板数据失败！");
            throw new GridReportException("加载报表模板数据失败！");
        }
        success = report.LoadDataFromXML(reportData);
        if (!success) {
            log.error("加载报表数据失败！");
            throw new GridReportException("加载报表数据失败！");
        }
        //处理报表参数
        for (Map.Entry<String, String> param : reportParams.entrySet()) {
            if (report.ParameterByName(param.getKey()) != null) {
                report.ParameterByName(param.getKey()).setAsString(param.getValue());
            }
        }
        BinaryObject bo = report.ExportDirectToBinaryObject(type);
        if (bo == null || bo.getNativeHandle() == 0) {
            log.error("导出二进制数据失败！");
            throw new GridReportException("导出二进制数据失败！");
        }
        String exportPathFile = this.gridReportOutPath + reportName + "." + type.toString().toLowerCase();
        bo.SaveToFile(exportPathFile);
        report.Release();
        return exportPathFile;
    }
}
