package nccloud.web.hrhi.cardrep.action;

import nc.bs.logging.Logger;
import nc.hr.utils.MultiLangHelper;
import nc.hr.utils.ResHelper;
import nc.itf.hr.frame.IPersistenceRetrieve;
import nc.itf.hr.tools.rtf.IGenerateRTFDocument;
import nc.ui.hr.tools.rtf.jacob.RtfHelper;
import nc.ui.hr.tools.rtf.jacob.WordUtil;
import nc.vo.hi.repdef.RepDefVO;
import nc.vo.hr.tools.rtf.RtfTemplateVO;
import nc.vo.pub.BusinessException;
import nc.vo.uif2.LoginContext;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.core.io.WebFile;
import nccloud.framework.service.ServiceLocator;
import nccloud.web.hr.pub.HRCommonAction;
import nccloud.web.uapbd.commons.web.ParamUtils;
import org.apache.commons.io.FileUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.jodconverter.JodConverter;
import org.jodconverter.office.LocalOfficeManager;
import org.jodconverter.office.LocalOfficeUtils;
import org.jodconverter.office.OfficeException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Base64;

/**
 * 人员卡片基础类
 *
 * @author chenchgf
 */
public abstract class CardrptBaseAction extends HRCommonAction {

	protected Object getObject(String operateType, ParamUtils param, LoginContext context) throws BusinessException {
		String pk_psnjob = param.getString("pk_psnjob", null);
		if (StringUtils.isBlank(pk_psnjob)) {
			throw new BusinessException(ResHelper.getString("6007psn", "16007psn0084")/* @res "未选择人员!" */);
		}
		String pk_rpt_def = param.getString("pk_rpt_def", null);
		if (StringUtils.isBlank(pk_rpt_def)) {
			throw new BusinessException(ResHelper.getString("6007psn", "16007psn0085")/* @res "未选择人员卡片!" */);
		}
		RepDefVO rptVO = (RepDefVO) ServiceLocator.find(IPersistenceRetrieve.class).retrieveByPk(null, RepDefVO.class, pk_rpt_def);

		String filePathName = null;
		String tempFile = null;
		String temprtfFile = null;
		try {
			String previewFileName = "preview_word_" + System.currentTimeMillis();
			tempFile = RtfHelper.strDocTempletDirPath + previewFileName + ".doc"; // ui包可用???
			temprtfFile = tempFile.replace(".doc", ".rtf");

			if (System.getProperty("os.name").startsWith("Windows")) {
				byte[] ba = WordUtil.changeTemplete(((RtfTemplateVO) rptVO.getObj_rpt_def()).getRtfDocument(), tempFile);
				((RtfTemplateVO) rptVO.getObj_rpt_def()).setRtfDocument(ba);
			}

			IGenerateRTFDocument grd = ServiceLocator.find(IGenerateRTFDocument.class);
			byte bytes[] = grd.createRtfFile(context, pk_psnjob, "psndoc", rptVO, null);

			String rptName = (String) rptVO.getAttributeValue(RepDefVO.RPT_NAME + MultiLangHelper.getLangIndex());
			String currentTime = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss").format(System.currentTimeMillis());
			String filename = rptName + "_" + currentTime;
			filePathName = RtfHelper.strDocTempletDirPath + filename;
			FileUtils.writeByteArrayToFile(new File(filePathName + ".rtf"), bytes);

			if ("preview".equals(operateType)) {
				// 使用JodConverter直接将rtf转为html后内容有问题，所以先用JodConverter将rtf转为doc，再用poi将doc转为html
				convertFileFormatWithJod(filePathName + ".rtf", filePathName + ".doc");
				convertDocToHtmlWithPoi(filePathName + ".doc", filePathName + ".html");
				return FileUtils.readFileToString(new File(filePathName + ".html"), "UTF-8");
			} else if ("export".equals(operateType)) {
				ByteArrayInputStream bis = new ByteArrayInputStream(FileUtils.readFileToByteArray(new File(filePathName + ".rtf")));
				WebFile webfile = new WebFile(filename + ".rtf", bis);
				return webfile;
			} else {
				return null;
			}
		} catch (Exception e) {
			Logger.error(e.getMessage(), e);
			throw new BusinessException(ResHelper.getString("6007psn", "06007psn0015")/* @res "卡片报表导出发生错误!" */ + " " + e.getMessage());
		} finally {
			WordUtil.deleteTempFile(tempFile);
			WordUtil.deleteTempFile(temprtfFile);
			WordUtil.deleteTempFile(filePathName + ".rtf");
			WordUtil.deleteTempFile(filePathName + ".html");
			deleteAllTempFile(filePathName + ".files");
		}
	}

	/**
	 * 使用JodConverter转换文件格式
	 *
	 * @param inputFilename
	 * @param outputFilename
	 * @throws BusinessException
	 */
	private void convertFileFormatWithJod(String inputFilename, String outputFilename) throws BusinessException {
		Logger.error("JodConverter: convert begin...");
		LocalOfficeManager officeManager = null;
		try {

			if (System.getProperty("os.name").startsWith("Windows")) {
				Logger.error("JodConverter for Windows: os.name : " + System.getProperty("os.name"));
				officeManager = LocalOfficeManager.builder().install().build();
			} else if (System.getProperty("os.name").startsWith("Linux")) {
				Logger.error("JodConverter for Linux: os.name : " + System.getProperty("os.name"));
				officeManager = LocalOfficeManager.builder().install().build();
			} else {
				Logger.error("JodConverter for Other System: os.name : " + System.getProperty("os.name"));
				officeManager = LocalOfficeManager.builder().install().build();
				// throw new BusinessException("JodConverter: Unsupported System!");
			}
			Logger.error("JodConverter using office home: " + LocalOfficeUtils.getDefaultOfficeHome());
		} catch (Exception e) {
			throw new BusinessException(ResHelper.getString("6007psn", "16007psn0088")/* @res "未安装" */ + " OpenOffice " +
					ResHelper.getString("6007psn", "16007psn0089")/* @res "或" */ + " LibreOffice!\n", e);
		}

		try {
			officeManager.start();
		} catch (OfficeException e) {
			Logger.error("Office manager failed to start!", e);
			throw new BusinessException("Office manager failed to start! Please check if you have any disk space left!", e);
		}
		try {
			JodConverter.convert(new File(inputFilename)).to(new File(outputFilename)).execute();
		} catch (OfficeException e) {
			Logger.error("Office manager failed to convert!", e);
			// throw new BusinessException("JodConverter converting gets wrong!", e);
		}
		try {
			officeManager.stop();
		} catch (OfficeException e) {
			Logger.error("Office manager failed to stop!", e);
			throw new BusinessException("Office manager failed to stop!", e);
		}
		Logger.error("JodConverter: convert rtf to doc finished...");
	}

	/**
	 * poi方式 - convert doc to html
	 *
	 * @param inputFilename
	 * @param outputFilename
	 * @throws TransformerException
	 * @throws IOException
	 * @throws ParserConfigurationException
	 */
	public static void convertDocToHtmlWithPoi(String inputFilename, String outputFilename)
			throws TransformerException, IOException, ParserConfigurationException {
		Base64.Encoder encoder = Base64.getEncoder();
		HWPFDocument wordDocument = new HWPFDocument(new FileInputStream(inputFilename));

		WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
				DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
		wordToHtmlConverter.setPicturesManager(new PicturesManager() {
			public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches,
									  float heightInches) {
				String encodedText = new String(encoder.encode(content));
				String imgSrc = "data:" + pictureType.getMime() + ";" + "base64," + encodedText;
				return imgSrc;
			}
		});
		wordToHtmlConverter.processDocument(wordDocument);

		org.w3c.dom.Document htmlDocument = wordToHtmlConverter.getDocument();
		DOMSource domSource = new DOMSource(htmlDocument);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		StreamResult streamResult = new StreamResult(out);

		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer serializer = tf.newTransformer();
		serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
		serializer.setOutputProperty(OutputKeys.INDENT, "yes");
		serializer.setOutputProperty(OutputKeys.METHOD, "html");
		serializer.transform(domSource, streamResult);
		out.close();
		FileUtils.writeByteArrayToFile(new File(outputFilename), out.toByteArray());
		Logger.error("PoiConverter: convert doc to html finished...");
	}

	/**
	 * 删除临时文件夹
	 *
	 * @param strBaseDir
	 */
	private void deleteAllTempFile(String strBaseDir) {
		File f = new File(strBaseDir);
		if (!f.exists()) {
			return;
		}
		File fa[] = f.listFiles();

		try {
			for (int i = 0; i < fa.length; i++) {
				fa[i].delete();
			}
			f.delete();
		} catch (Exception e) {
			/** 忽略，有可能正在被使用 */
		}
	}
}
