package com.qmth.qrzk.repository.utils.docx;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.xml.transform.TransformerException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.dom4j.io.SAXReader;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;

import com.qmth.qrzk.repository.utils.Consts;
import com.qmth.qrzk.repository.utils.General;
import com.qmth.qrzk.repository.utils.ParamUtils;
import com.qmth.qrzk.repository.utils.Wmf2Png;
import com.qmth.qrzk.repository.utils.docx.html.B;
import com.qmth.qrzk.repository.utils.docx.html.Background;
import com.qmth.qrzk.repository.utils.docx.html.Border;
import com.qmth.qrzk.repository.utils.docx.html.Del;
import com.qmth.qrzk.repository.utils.docx.html.Font;
import com.qmth.qrzk.repository.utils.docx.html.HtmlElement;
import com.qmth.qrzk.repository.utils.docx.html.I;
import com.qmth.qrzk.repository.utils.docx.html.Img;
import com.qmth.qrzk.repository.utils.docx.html.Shading;
import com.qmth.qrzk.repository.utils.docx.html.Sub;
import com.qmth.qrzk.repository.utils.docx.html.Sup;
import com.qmth.qrzk.repository.utils.docx.html.Text;
import com.qmth.qrzk.repository.utils.docx.html.U;
import com.qmth.qrzk.repository.utils.docx.num.AbstractNum;
import com.qmth.qrzk.repository.utils.docx.num.Level;

import net.arnx.wmf2svg.gdi.svg.SvgGdiException;
import net.arnx.wmf2svg.gdi.wmf.WmfParseException;

public class HtmlCreator {

	private static final Namespace NS_W = new Namespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
	
	public static void main(String argv[]) {
		try {
//			{
//				File docFile = new File("E:/temp/doc/10.doc");
//				FileOutputStream fos = new FileOutputStream(new File(docFile.getAbsoluteFile() + ".html"), false);
//				IOUtils.write(docToHtml(new FileInputStream(docFile)).getOriginalHtml(), fos, "UTF-8");
//			}
			{
//				File docFile = new File("E:/temp/doc/12.docx");
				File docFile = new File("/Users/songyue/OUT_maths.docx");
				FileOutputStream fos = new FileOutputStream(new File(docFile.getAbsoluteFile() + ".html"), false);
				IOUtils.write(covertToHtml(IOUtils.toByteArray(new FileInputStream(docFile))).toString(), fos, "UTF-8");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static StringBuffer covertToHtml(byte[] wordBinary) throws IOException, DocumentException{
		return covertToHtml(wordBinary,null);
	}
	
	/**
	 * 把二进制数组表示的2007+的word转成html字符串
	 * @param wordBinary 2007+的word二进制数组
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static StringBuffer covertToHtml(byte[] wordBinary,String title) throws IOException, DocumentException{
		File newDocx = null;
		DocxReader xtReader = null;
		try{
			{//把内存的数据写入到临时文件里面，方便后面的逻辑使用
				FileOutputStream fos = null;
				try{
					newDocx = new File(ParamUtils.TemporaryDirPath,UUID.randomUUID().toString());
					fos = new FileOutputStream(newDocx);
					IOUtils.write(wordBinary, fos);
					fos.flush();
				}finally{
					General.close(fos);
				}
			}
			xtReader = new DocxReader(newDocx);
			xtReader.doRead();
			return covertToHtml(xtReader,title);
		}finally{
			General.delete(newDocx);
			General.release(xtReader);
		}
	}

	public static StringBuffer covertToHtml(DocxReader docxReader,String title) throws DocumentException, IOException{
		Map<String,ResourceInfo> imgMap = new HashMap<String, ResourceInfo>();
		for(ResourceInfo img:docxReader.getImgs()){
			imgMap.put(img.getId(), img);
		}
		InputStream documentXmlIs = null;
		try{
			documentXmlIs = new FileInputStream(docxReader.getDocumentInfo().getFile());
			StringBuffer htmlStr = new StringBuffer();
//			htmlStr.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
//			htmlStr.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />");
			if(General.isNotEmpty(title)){
				//htmlStr.append("<title>" + title + "</title>");
			}
//			htmlStr.append("<style>.wordTd_disabled{border:solid windowtext 1pt;padding:0cm 5.4pt 0cm 5.4pt;} p{white-space:sWrap;word-wrap:break-word;} span{white-space:sWrap;word-wrap:break-word;}</style></head><body>");
			SAXReader reader = new SAXReader();
			Document document = reader.read(documentXmlIs);
			Element root = document.getRootElement();
			Element body = root.element(new QName("body", NS_W));
			for (Object obj : body.elements()) {
				Element ele = (Element) obj;
				String eleName = ele.getName();
				if(eleName.equals("p")){
					htmlStr.append(parseWP(ele,imgMap,docxReader.getNumMap()));
				}else if(eleName.equals("tbl")){
					htmlStr.append(parseTbl(ele,imgMap,docxReader.getNumMap()));
				}
			}
			String tempStr = htmlStr.toString();
		    tempStr = repairHtmlBR(tempStr);
		    if(General.isNotEmpty(title)){
		    	tempStr = tempStr.replace("<head></head>", "<head><title>" + title + "</title></head>");
			}
			htmlStr = new StringBuffer(tempStr);
			//htmlStr.append("</body></html>");
			return htmlStr;
		}finally{
			General.close(documentXmlIs);
		}
	}
	
	private static final String NOBORDER_STYLE = "border:none;";
	
	@SuppressWarnings("unchecked")
	private static StringBuffer parseTbl(Element tbl,Map<String,ResourceInfo> imgMap,Map<String,AbstractNum> numMap) throws IOException{
		String marginLeft = "";
		Attribute tblInd = (Attribute) tbl.selectSingleNode("w:tblPr/w:tblInd/attribute::w:w");
		if(tblInd != null){
			String widthStr = tblInd.getText();
			String width = Integer.parseInt(widthStr)/20.0 + "pt";
			marginLeft = "margin-left:" + width + ";";
		}
		StringBuffer htmlStr = new StringBuffer("<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"" + marginLeft + "border-collapse:collapse;border:none;\">");
		List<Object> trs = tbl.elements("tr");
		for(int i=0;i<trs.size();i++){
			Element tr = (Element)trs.get(i);
			List<Object> tds = tr.elements("tc");
			htmlStr.append("<tr>");
			Element wBefore = (Element)tr.selectSingleNode("w:trPr/w:wBefore");
			Element wAfter = (Element)tr.selectSingleNode("w:trPr/w:wAfter");
			if(wBefore != null){
				String widthStr = wBefore.attributeValue("w");
				String width = Integer.parseInt(widthStr)/20.0 + "pt";
				htmlStr.append("<td style=\"width:" + width + ";" + NOBORDER_STYLE + "\">&nbsp;</td>");
			}
			int curColNum = (wBefore != null)?1:0;
			for(int j=0;j<tds.size();j++){
				Element td = (Element)tds.get(j);
				String rowspanStr = "";
				String colspanStr = "";
				Element vMerge = (Element)td.selectSingleNode("w:tcPr/w:vMerge");
				boolean needContinue = false;
				if(vMerge != null){
					Attribute val = vMerge.attribute("val");
					if(val == null){
						needContinue = true;;
					}else if("restart".equals(val.getText())){
						rowspanStr = " rowspan=\"" + calcRowspan(i, curColNum, trs) + "\"";
					}
				}
				Attribute tcw = (Attribute) td.selectSingleNode("w:tcPr/w:tcW/attribute::w:w");
				String widthStr = tcw.getText();
				String width = Integer.parseInt(widthStr)/20.0 + "pt";
				Attribute gridSpan = (Attribute) td.selectSingleNode("w:tcPr/w:gridSpan/attribute::w:val");
				if(gridSpan != null){
					int colspan = Integer.parseInt(gridSpan.getText());
					colspanStr = " colspan=\"" + colspan + "\"";
					curColNum += colspan;
				}else{
					curColNum++;
				}
				if(needContinue){
					continue;
				}
				htmlStr.append("<td").append(" class=\"wordTd\"").append(rowspanStr).append(colspanStr).append(" style=\"border:solid windowtext 1pt;padding:0cm 5.4pt 0cm 5.4pt;width:" + width + ";\"").append(">");
				for(Object pEle:td.elements("p")){
					htmlStr.append(parseWP((Element) pEle,imgMap,numMap,"div"));
				}
				htmlStr.append("</td>");
			}
			if(wAfter != null){
				String widthStr = wAfter.attributeValue("w");
				String width = Integer.parseInt(widthStr)/20.0 + "pt";
				htmlStr.append("<td style=\"width:" + width + ";" + NOBORDER_STYLE + "\">&nbsp;</td>");
			}
			htmlStr.append("</tr>");
		}
		htmlStr.append("<![if !supportMisalignedColumns]><tr height=0>");
		for(Object gridCol:tbl.selectNodes("w:tblGrid/w:gridCol")){
			String widthStr = ((Element)gridCol).attributeValue("w");
			String width = Integer.parseInt(widthStr)/20.0 + "pt";
			htmlStr.append("<td style=\"width:" + width + ";" + NOBORDER_STYLE + "\"></td>");
		}
		htmlStr.append("</tr><![endif]>");
		htmlStr.append("</table>");
		return htmlStr;
	}
	
	private static int calcRowspan(int curRowNum,int curColNum,List<Object> trs){
		int rowspan = 1;
		for(int i=curRowNum+1;i<trs.size();i++){
			Element tr = (Element)trs.get(i);
			@SuppressWarnings("unchecked")
			List<Object> tds = tr.elements("tc");
			Element wBefore = (Element)tr.selectSingleNode("w:trPr/w:wBefore");
			int curColNumTmp = (wBefore != null)?1:0;
			boolean hasVMerge = false;
			for(int j = 0;j<tds.size();j++){
				Element td = (Element)tds.get(j);
				if(curColNum == curColNumTmp){
					Element vMerge = (Element)td.selectSingleNode("w:tcPr/w:vMerge");
					if(vMerge != null){
						Attribute val = vMerge.attribute("val");
						if(val == null){
							hasVMerge = true;
							rowspan++;
						}
					}
				}
				Attribute gridSpan = (Attribute) td.selectSingleNode("w:tcPr/w:gridSpan/attribute::w:val");
				if(gridSpan != null){
					int colspan = Integer.parseInt(gridSpan.getText());
					curColNumTmp += colspan;
				}else{
					curColNumTmp++;
				}
			}
			if(!hasVMerge){
				break;
			}
		}
		return rowspan;
	}
	
	private static StringBuffer parseWP(Element wp,Map<String,ResourceInfo> imgMap,Map<String,AbstractNum> numMap) throws IOException{
		return parseWP(wp, imgMap, numMap, null);
	}
	
	private static StringBuffer parseWP(Element wp,Map<String,ResourceInfo> imgMap,Map<String,AbstractNum> numMap,String label) throws IOException{
		if(label == null || label.equals("")){
			label = "p";
		}
		String textIndent = "";
		String marginLeft = "";
		Attribute firstLine = (Attribute) wp.selectSingleNode("w:pPr/w:ind/attribute::w:firstLine");
		Attribute hanging = (Attribute) wp.selectSingleNode("w:pPr/w:ind/attribute::w:hanging");
		Attribute left = (Attribute) wp.selectSingleNode("w:pPr/w:ind/attribute::w:left");
		int indent = 0;
		int leftInt = 0;
		if(firstLine != null){
			indent = Integer.parseInt(firstLine.getText());
		}else if(hanging != null){
			indent = -Integer.parseInt(hanging.getText());
		}
		if(left != null){
			leftInt = Integer.parseInt(left.getText());
		}
		if(indent != 0){
			String width = indent/20.0 + "pt";
			textIndent = "text-indent:" + width + ";";
		}
		if(leftInt != 0){
			String width = leftInt/20.0 + "pt";
			marginLeft = "margin-left:" + width + ";";
		}
		StringBuffer htmlStr = null;
		Element ppr = wp.element("pPr");
		NumHtml numHtml = null;
		if(ppr != null){
			Element numPr = ppr.element("numPr");
			if(numPr != null){
				htmlStr = new StringBuffer("<div style=\"");
				numHtml = parseNum(numPr, imgMap, numMap);
				marginLeft = "margin-left:" + numHtml.marginLeft + ";";
				textIndent = "text-indent:" + numHtml.textIndent + ";";
			}else{
				htmlStr = new StringBuffer("<" + label + " style=\"");
			}
			htmlStr.append(marginLeft).append(textIndent);
			
			htmlStr.append(getTextAlignStyle(ppr));
			Element rpr = ppr.element("rPr");
			if(rpr != null){
				List<HtmlElement> allStyles = getRprAllStyles(rpr);
				htmlStr.append(mergeStylesInOneStyle(allStyles));
			}
		}else{
			htmlStr = new StringBuffer("<" + label + " style=\"");
			htmlStr.append(marginLeft).append(textIndent);
		}
		htmlStr.append("\">");
		if(numHtml != null){
			htmlStr.append(numHtml.htmlStr);
		}
		//暂时不考虑序列，当做普通的文本处理
		List<Text> textList = new ArrayList<Text>();
		iterWp(textList, wp, imgMap);
		
		if(textList.size() == 0){
			htmlStr.append("<br/>");
		}else{
			htmlStr.append(toSpanHtml(textList));
		}
		htmlStr.append((numHtml != null)?"</div>":("</" + label + ">"));
		return htmlStr;
	}
	
	private static void iterWp(List<Text> textList,Element wp,Map<String,ResourceInfo> imgMap) throws IOException{
		for (Object obj : wp.elements()) {
			Element ele = (Element) obj;
			String eleName = ele.getName();
			if(!eleName.equals("pPr")){
				if(eleName.equals("r")){
					Element rpr = ele.element("rPr");
					
					{
						Element t = ele.element("t");
						if(t != null){
							textList.add(new Text(new StringBuffer(t.getText()),getRprAllStyles(rpr)));
						}
					}
					
					{
						Element drawing = ele.element("drawing");
						if(drawing != null){
							StringBuffer imgHtml = getImgHtml(drawing, imgMap);
							if(imgHtml != null){
								textList.add(new Img(imgHtml,getRprAllStyles(rpr)));
							}
						}
					}
					
					{
						Element object = ele.element("object");
						if(object != null){
							StringBuffer imgHtml = getObjHtml(object, imgMap);
							if(imgHtml != null){
								textList.add(new Img(imgHtml,getRprAllStyles(rpr)));
							}
						}
					}
					//处理公式，采用微软模板转换成mathml作为属性放进图片中 update by songyue
				}else if(eleName.equals("oMathPara")){
					textList.add(new Img(getMathImgHtml(ele.element("oMath")), new ArrayList<HtmlElement>()));
					//textList.add(new Mathml(getCommonMathml(ele.element("oMath")), new ArrayList<HtmlElement>()));
				}else if(eleName.equals("oMath")){
					textList.add(new Img(getMathImgHtml(ele), new ArrayList<HtmlElement>()));
					//textList.add(new Mathml(getCommonMathml(ele), new ArrayList<HtmlElement>()));
				}else if(eleName.equals("hyperlink")){//超链接当做普通的w:r处理
					iterWp(textList,ele,imgMap);
				}else if(eleName.equals("smartTag")){
					iterWp(textList,ele,imgMap);
				}
			}
		}
	}
	
	private static StringBuffer getMathImgHtml(Element oMath) throws IOException{
		StringBuffer imgHtml = new StringBuffer();
		StringBuffer mathml = General.omml2mml(oMath);
//		imgHtml.append("<img class=\"math\" data-mathml='").append(mathml).append("' align=\"middle\" style=\"vertical-align:middle;\" src=\"data:image/png;base64,")
//			.append(new String(General.convertToBase64Img(MathMlDeal.toMathMlStr(oMath))))
//			.append("\"/>");
		imgHtml.append("<img class=\"math\" align=\"middle\" style=\"vertical-align:middle;\" src=\"data:image/png;base64,")
		.append(new String(General.convertToBase64Img(mathml)))
		.append("\"/>");
		return imgHtml;
	}
	
	private static StringBuffer getCommonMathml(Element oMath) throws IOException{
		StringBuffer mathmlHtml = new StringBuffer();
		mathmlHtml.append("<span class='mathml'>")
			.append(General.omml2mml(oMath))
			.append("</span>");
		return mathmlHtml;
	}
	
	private static StringBuffer mergeStylesInOneStyle(List<HtmlElement> styles){
		StringBuffer style = new StringBuffer();
		for(HtmlElement htmlEle:styles){
			style.append(htmlEle.getStyleStr());
		}
		return style;
	}
	
	private static NumHtml parseNum(Element numPr,Map<String,ResourceInfo> imgMap,Map<String,AbstractNum> numMap) throws IOException{
		NumHtml numHtml = new NumHtml();
		StringBuffer htmlStr = new StringBuffer();
		String ilvl = numPr.element("ilvl").attributeValue("val");
		int curLvl = Integer.parseInt(ilvl);
		String numId = numPr.element("numId").attributeValue("val");
		AbstractNum absNum = numMap.get(numId);
		if(absNum == null){
			absNum = new AbstractNum("", "");
		}
		Level level = absNum.getLevelMap().get(ilvl);
		if(level == null){
			level = new Level("", 0, "", "", "", "0", "0",new ArrayList<HtmlElement>());
		}
		String numFmt = level.getNumFmt();
		String lvlText = level.getLvlText();
		int curIndex = level.getCurIndex();
		for(int i=curLvl + 1;i<20;i++){
			Level sub = absNum.getLevelMap().get("" + i);
			if(sub != null){
				sub.restCurIndex();
			}
		}
		String numStr = null;
		if(numFmt.equals("bullet")){
			if(lvlText == null || lvlText.equals("") || level.getLvlPicBulletId() != null){
				numStr = "<span style=\"font-family:Wingdings;\">&#61548;</span>";
			}else{
				numStr = General.toUnicode(lvlText);
			}
		}else{
			lvlText = General.toJavaFormat(lvlText);
			String[] seqArr = new String[curLvl + 1];
			for(int i=0;i<=curLvl;i++){
				int index = 0;
				if(i < curLvl){
					index = absNum.getLevelMap().get("" + i).getCurIndexFromSub();
				}else{
					index = curIndex;
				}
				seqArr[i] = "" + index;
				if(numFmt.equals("decimal")){
					seqArr[i] = "" + index;
				}else if(numFmt.equals("lowerLetter")){
					seqArr[i] = "" + (char)('a' + index - 1);
				}else if(numFmt.equals("upperLetter")){
					seqArr[i] = "" + (char)('A' + index - 1);
				}else if(numFmt.equals("lowerRoman")){
					seqArr[i] = General.toLowerRoman(index);
				}else if(numFmt.equals("upperRoman")){
					seqArr[i] = General.toUpperRoman(index);
				}else if(numFmt.equals("chineseCountingThousand")){
					seqArr[i] = General.toCNLowerNum(index);
				}else if(numFmt.equals("chineseLegalSimplified")){
					seqArr[i] = General.toCNUpperNum(index);
				}else{
					seqArr[i] = "" + index;
				}
			}
			numStr = String.format(lvlText, seqArr);
		}
		List<Text> textList = new ArrayList<Text>();
		textList.add(new Text(new StringBuffer(numStr),new ArrayList<HtmlElement>(level.getFonts())));
		htmlStr.append("<span>").append(toSpanHtml(textList)).append("</span><span style=\"font:7.0pt 'Times New Roman';\">&nbsp;&nbsp;&nbsp;&nbsp;</span>");
		numHtml.htmlStr = htmlStr;
		numHtml.marginLeft = (General.toInteger(level.getLeft(),0)/20.0) + "pt";
		numHtml.textIndent = (General.toInteger(level.getHanging(),0)/-20.0) + "pt";
		return numHtml;
	}
	
	static class NumHtml{
		String marginLeft;
		String textIndent;
		StringBuffer htmlStr;
	}
	
	private static StringBuffer getImgHtml(Element drawing,Map<String,ResourceInfo> imgMap) throws IOException{
		StringBuffer imgHtml = null;
		drawing.addNamespace("wp", "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing");
		drawing.addNamespace("a", "http://schemas.openxmlformats.org/drawingml/2006/main");
		drawing.addNamespace("pic", "http://schemas.openxmlformats.org/drawingml/2006/picture");
		Element pic = (Element) drawing.selectSingleNode("wp:inline/a:graphic/a:graphicData/pic:pic");
		if(pic != null){
			Attribute embed = (Attribute) pic.selectSingleNode("pic:blipFill/a:blip/attribute::r:embed");
			if(embed != null){
				String picId = embed.getText();
				ResourceInfo img = imgMap.get(picId);
				if(img != null){
					Attribute cx = (Attribute) pic.selectSingleNode("pic:spPr/a:xfrm/a:ext/attribute::cx");
					Attribute cy = (Attribute) pic.selectSingleNode("pic:spPr/a:xfrm/a:ext/attribute::cy");
					String widthStr = cx.getText();
					double width = Integer.parseInt(widthStr)/360000.0;//单位里面：cm
					String heightStr = cy.getText();
					double height = Integer.parseInt(heightStr)/360000.0;//单位里面：cm
					
					imgHtml = new StringBuffer();
					imgHtml.append("<img src=\"").append(readPicture(img).getDealHtml())
						.append("\" align=\"middle\" style=\"vertical-align:middle;border-width:0px;width:").append(width).append("cm;height:")
						.append(height).append("cm;\"/>");
					
				}
			}
			
		}
		return imgHtml;
	}
	
	private static StringBuffer getObjHtml(Element object,Map<String,ResourceInfo> imgMap) throws IOException{
		StringBuffer imgHtml = null;
		object.addNamespace("v", "urn:schemas-microsoft-com:vml");
		Element pic = (Element) object.selectSingleNode("v:shape/v:imagedata");
		if(pic != null){
			Attribute rId = pic.attribute("id");
			if(rId != null){
				String picId = rId.getText();
				ResourceInfo img = imgMap.get(picId);
				if(img != null){
					Attribute styleAttr = (Attribute) object.selectSingleNode("v:shape/attribute::style");
					String styleStr = styleAttr.getText();
					
					imgHtml = new StringBuffer();
					imgHtml.append("<img src=\"").append(readPicture(img).getDealHtml())
						.append("\" align=\"middle\" style=\"vertical-align:middle;border-width:0px;").append(styleStr).append("\"/>");
					
				}
			}
			
		}
		return imgHtml;
	}


	/**
	 * 读写文档中的图片
	 * 
	 * @param pTable
	 * @param cr
	 * @throws IOException 
	 * @throws TransformerException 
	 * @throws WmfParseException 
	 * @throws SvgGdiException 
	 * @throws Exception
	 */
	private static ImgInfo readPicture(ResourceInfo imgResourceInfo) throws IOException{
		ImgInfo img = null;
		File originalFile = imgResourceInfo.getFile();
		String fileName = originalFile.getName();
		File dealFile = null;
		OutputStream out = null;
		try{
//			log.info(fileName + "\t" + originalFile.getName());
			int splitAt = fileName.lastIndexOf('.');
			String imgType = "png";
			if (splitAt > 0) {
				imgType = fileName.substring(splitAt + 1).trim().toLowerCase();
				if(imgType.length() == 0){
					imgType = "png";
				}
			}
			String originalHtml = "data:" + Consts.ImgType.ImgTypeMap.get(imgType) + ";base64," + new String(General.getImageByteArr(originalFile));
			img = new ImgInfo(imgType, fileName,originalFile,originalHtml);
			if(imgType.equals(Consts.ImgType.wmf)) {
				dealFile = new File(ParamUtils.TemporaryDirPath, UUID.randomUUID().toString());
				dealFile.createNewFile();
				try{
					Wmf2Png.wmf2Svg(originalFile, dealFile);
				}catch(Exception e){
					throw new IOException("wmf转svg格式失败，原因：" + e.getMessage(), e);
				}
				img.setDealHtml("data:image/svg+xml;base64," + new String(General.getImageByteArr(dealFile)));
			}else if(imgType.equals(Consts.ImgType.emf)) {
				dealFile = new File(ParamUtils.TemporaryDirPath, UUID.randomUUID().toString());
				dealFile.createNewFile();
				Wmf2Png.emf2Png(originalFile, dealFile);
				img.setDealHtml("data:image/png;base64," + new String(General.getImageByteArr(dealFile)));
			}else {
				img.setDealHtml(img.getOriginalHtml());
			}
		}finally{
			General.close(out);
		}
		return img;
	}
	
	private static String getFontSize (Element rpr,boolean hasSubOrSup){
		String size = null;
		if(rpr != null){
			Element sz = rpr.element("sz");
			if(sz != null){
				size = sz.attributeValue("val");
				if(size != null){
					size = (Integer.parseInt(size)/(hasSubOrSup?3:2)) + "pt";
				}
			}
		}
		if(size == null){
			size = "";
		}
		return size;
	}
	
	private static String getFontColor (Element rpr){
		String color = null;
		if(rpr != null){
			Element rColor = rpr.element("color");
			if(rColor != null){
				color = rColor.attributeValue("val");
			}
		}
		return General.getRealColor(color);
	}
	
	/**
	 * 是不是粗体
	 * @param rpr
	 * @return
	 */
	private static B getB (Element rpr){
		Element parent = rpr.getParent();
		if(parent.getName().equals("pPr")){
			return null;
		}
		if(rpr != null){
			Element b = rpr.element("b");
			if(b != null){
				Attribute val = b.attribute("val");
				boolean none = (val != null && !General.toBoolean(val.getText(), false));
				return new B(none);
			}
		}
		return null;
	}
	
	/**
	 * 是不是斜体
	 * @param rpr
	 * @return
	 */
	private static I getI (Element rpr){
		Element parent = rpr.getParent();
		if(parent.getName().equals("pPr")){
			return null;
		}
		if(rpr != null){
			Element i = rpr.element("i");
			if(i != null){
				Attribute val = i.attribute("val");
				boolean none = (val != null && !General.toBoolean(val.getText(), false));
				return new I(none);
			}
		}
		return null;
	}
	
	/**
	 * 是不是下划线
	 * @param rpr
	 * @return
	 */
	private static U getU (Element rpr){
		Element parent = rpr.getParent();
		if(parent.getName().equals("pPr")){
			return null;
		}
		if(rpr != null){
			Element u = rpr.element("u");
			if(u != null){
				Attribute val = u.attribute("val");
				boolean none = (val != null && !General.toBoolean(val.getText(), false));
				return new U(none);
			}
		}
		return null;
	}
	
	/**
	 * 是不是着重号，由于着重号在浏览器里面无法展现，所以也用下划线来表现
	 * @param rpr
	 * @return
	 */
	private static U getEm (Element rpr){
		Element parent = rpr.getParent();
		if(parent.getName().equals("pPr")){
			return null;
		}
		if(rpr != null){
			Element em = rpr.element("em");
			if(em != null){
				Attribute val = em.attribute("val");
				boolean none = (val != null && !General.toBoolean(val.getText(), false));
				return new U(none);
			}
		}
		return null;
	}
	
	/**
	 * 是不是删除线
	 * @param rpr
	 * @return
	 */
	private static Del getDel (Element rpr){
		Element parent = rpr.getParent();
		if(parent.getName().equals("pPr")){
			return null;
		}
		if(rpr != null){
			Element strike = rpr.element("strike");
			if(strike != null){
				Attribute val = strike.attribute("val");
				boolean none = (val != null && !General.toBoolean(val.getText(), false));
				return new Del(none);
			}
		}
		return null;
	}
	
	/**
	 * 是不是下标
	 * @param rpr
	 * @return
	 */
	private static Sub getSub (Element rpr){
		return rpr != null && (rpr.element("vertAlign") != null) && ("subscript".equals(rpr.element("vertAlign").attributeValue("val"))) ? new Sub():null;
	}
	
	/**
	 * 是不是上标
	 * @param rpr
	 * @return
	 */
	private static Sup getSup (Element rpr){
		return rpr != null && (rpr.element("vertAlign") != null) && ("superscript".equals(rpr.element("vertAlign").attributeValue("val"))) ? new Sup():null;
	}
	
	private static String getTextAlignStyle(Element ppr){
		String algin = null;
		if(ppr != null){
			Element jc = ppr.element("jc");
			if(jc != null){
				Attribute val = jc.attribute("val");
				if(val != null){
					algin = val.getText();
				}
			}
		}
		return (algin != null && !algin.equals("")) ? ("text-align:" + algin + ";") : "";
	}
	
	private static String getFontName(Element rpr){
		String fontName = null;
		if(rpr != null){
			Element rFonts = rpr.element("rFonts");
			if(rFonts != null){
				fontName = rFonts.attributeValue("ascii");
				if(fontName == null){
					fontName = rFonts.attributeValue("eastAsia");
				}
				if(fontName == null){
					fontName = rFonts.attributeValue("hAnsi");
				}
				if(fontName == null){
					fontName = rFonts.attributeValue("hint");
				}
				if("eastAsia".equals(fontName)){
					fontName = "Calibri";
				}
			}
		}
		if(fontName == null){
			fontName = "";
		}
		return fontName;
	}
	
	private static Font getFont(Element rpr,boolean hasSubOrSup){
		Font font = null;
		String size = getFontSize(rpr,hasSubOrSup);
		String fontName = getFontName(rpr);
		String fontColor = getFontColor(rpr);
		if(!size.equals("") || !fontName.equals("") || !fontColor.equals("")){
			font = new Font(fontColor, size, fontName);
		}
		return font;
	}
	
	private static Background getBackgroundColor(Element rpr){
		Background bg = null;
		if(rpr != null){
			Element highlight = rpr.element("highlight");
			if(highlight != null){
				String color = highlight.attributeValue("val");
				if(color != null && !(color = General.getRealColor(color)).equals("")){
					bg = new Background(color);
				}
			}
		}
		return bg;
	}
	
	private static Shading getShading(Element rpr){
		Shading shading = null;
		if(rpr != null){
			Element shd = rpr.element("shd");
			if(shd != null){
				String fill = shd.attributeValue("fill");
				String color = shd.attributeValue("color");
				if(fill == null || fill.equals("")){
					fill = color;
				}
				if(fill != null && !(fill = General.getRealColor(fill)).equals("")){
					shading = new Shading(fill);
				}
			}
		}
		return shading;
	}
	
	private static Border getBorder(Element rpr){
		Border border = null;
		if(rpr != null){
			Element bdr = rpr.element("bdr");
			if(bdr != null){
				String style = General.getBorderStyle(bdr.attributeValue("val"));
				String color = General.getRealColor(bdr.attributeValue("color"));
				String width = bdr.attributeValue("sz");
				if(width != null && !width.equals("")){
					width = General.getBorderWidth(width);
					border = new Border(style, width, color);
				}
			}
		}
		return border;
	}
	
	public static List<HtmlElement> getRprAllStyles(Element rpr){
		List<HtmlElement> labels = new ArrayList<HtmlElement>();
		if(rpr == null){
			return labels;
		}
		Border border = getBorder(rpr);
		Background bg = getBackgroundColor(rpr);
		Shading shd = getShading(rpr);
		B b = getB(rpr);
		I i = getI(rpr);
		U u = getU(rpr);
		U em = getEm(rpr);
		Del del = getDel(rpr);
		Sub sub = getSub(rpr);
		Sup sup = getSup(rpr);
		Font font = getFont(rpr,(sub != null || sup != null));

		if(border != null){labels.add(border);}
		if(bg != null){labels.add(bg);}
		if(shd != null){labels.add(shd);}
		if(b != null){labels.add(b);}
		if(i != null){labels.add(i);}
		if(u != null){labels.add(u);}
		if(em != null){labels.add(em);}
		if(del != null){labels.add(del);}
		if(sub != null){labels.add(sub);}
		if(sup != null){labels.add(sup);}
		if(font != null){labels.add(font);}
		
		return labels;
	}
	
	private static StringBuffer toSpanHtml(List<Text> textList){
		List<ElementCount> countList = sortTextList(textList);
		StringBuffer html = new StringBuffer();
		toSpanHtml(html,countList);
		return html;
	}
	
	private static void toSpanHtml(StringBuffer html,List<ElementCount> countList){
		for(ElementCount c:countList){
			HtmlElement style = c.style;
			html.append(style.head());
			if(!(style instanceof Text)){
//				html.append('\n');
				toSpanHtml(html,c.childrenCount);
			}
			html.append(style.tail());
//			html.append('\n');
		}
	}
	
	private static List<ElementCount> sortTextList(final List<Text> textList){
		@SuppressWarnings("unchecked")
		Map<String,ElementCount>[] countMapArr = new Map[textList.size()];
		for(int i=0;i<textList.size();i++){
			Text t = textList.get(i);
			countMapArr[i] = new HashMap<String, ElementCount>();
			if(t.getStyles().size() > 0){
				for(HtmlElement style:t.getStyles()){
					countMapArr[i].put(style.head(), new ElementCount(style,t));
				}
				for(int j = i+1;j<textList.size();j++){
					Text ta = textList.get(j);
					for(Map.Entry<String,ElementCount> countEntry:countMapArr[i].entrySet()){
						String key = countEntry.getKey();
						ElementCount value = countEntry.getValue();
						if(!value.isEnd){
							value.isEnd = true;
							int maxPriority = 0;
							for(HtmlElement style:ta.getStyles()){
								if(maxPriority < style.getPriority()){
									maxPriority = style.getPriority();
								}
							}
							if(value.style.getPriority() >= maxPriority){
								for(HtmlElement style:ta.getStyles()){
									if(style.head().equals(key)){
										value.isEnd = false;
										value.count++;
										value.childrenText.add(ta);
									}
								}
							}
						}
					}
				}
			}
		}
		ElementCount[] maxCountArr = new ElementCount[countMapArr.length];
		for(int i=0;i<countMapArr.length;i++){
			Map<String,ElementCount> map = countMapArr[i];
			if(map.size() == 0){
				maxCountArr[i] = new ElementCount(textList.get(i),textList.get(i));
			}else{
				for(ElementCount count:map.values()){
					if(maxCountArr[i] == null){
						maxCountArr[i] = count;
					}else{
						if(maxCountArr[i].style.getPriority() < count.style.getPriority()){
							maxCountArr[i] = count;
						}else if(maxCountArr[i].style.getPriority() == count.style.getPriority() && maxCountArr[i].count < count.count){
							maxCountArr[i] = count;
						}
					}
				}
			}
		}
		List<ElementCount> maxCountList = new ArrayList<ElementCount>();
		Collections.addAll(maxCountList, maxCountArr);
		Collections.sort(maxCountList, new Comparator<ElementCount>() {
			@Override
			public int compare(ElementCount o1, ElementCount o2) {
				if(o1.style instanceof Text && !(o2.style instanceof Text)){
					return -1;
				}
				if(!(o1.style instanceof Text) && o2.style instanceof Text){
					return 1;
				}
				if(o1.style instanceof Text && o2.style instanceof Text){
					return 0;
				}
				if(o1.style.getPriority() > o2.style.getPriority()){
					return -1;
				}
				if(o1.style.getPriority() == o2.style.getPriority()){
					return o2.count - o1.count;
				}
				if(o1.style.getPriority() < o2.style.getPriority()){
					return 1;
				}
				return 0;
			}
		});
		List<Text> textListTmp = new ArrayList<Text>(textList);
		for(int j = 0;j<maxCountList.size();j++){
			ElementCount c = maxCountList.get(j);
			for(int i=0;i<c.childrenText.size();i++){
				if(textListTmp.contains(c.childrenText.get(i))){
					textListTmp.remove(c.childrenText.get(i));
				}else{
					c.childrenText.remove(i);
					i--;
				}
			}
			if(c.childrenText.size() == 0){
				maxCountList.remove(j);
				j--;
			}
		}
		Collections.sort(maxCountList, new Comparator<ElementCount>() {
			@Override
			public int compare(ElementCount o1, ElementCount o2) {
				return textList.indexOf(o1.childrenText.get(0)) - textList.indexOf(o2.childrenText.get(0));
			}
		});
		for(ElementCount c:maxCountList){
			String c_style_head = c.style.head();
			for(Text t:c.childrenText){
				for(int i=0;i<t.getStyles().size();i++){
					if(t.getStyles().get(i).head().equals(c_style_head)){
						t.getStyles().remove(i);
						break;
					}
				}
			}
			if(!(c.style instanceof Text)){
				c.childrenCount.addAll(sortTextList(c.childrenText));
			}
		}
		return maxCountList;
	}
	
	static class ElementCount{
		HtmlElement style = null;
		int count = 1;
		boolean isEnd = false;
		List<Text> childrenText = new ArrayList<Text>();
		List<ElementCount> childrenCount = new ArrayList<ElementCount>();
		public ElementCount(HtmlElement style,Text t) {
			this.style = style;
			childrenText.add(t);
		}
	}
	
	/**
	 * <p>过滤最后的换行符、空P标签,去除多余标签</p>
	 * @author songyue
	 * @date
	 */
	public static String repairHtmlBR(String htmlStr){
		htmlStr = htmlStr.replaceAll("(<br>|<br/>)+$", "");
		try{
			org.jsoup.nodes.Document doc = Jsoup.parse(htmlStr);
			Elements pbr = doc.select("p:has(br)");
			for(org.jsoup.nodes.Element e : pbr){
				if(StringUtils.isBlank(e.text())){
					e.remove();
				}
			}
			Elements span = doc.select("span");
			for(org.jsoup.nodes.Element e : span){
				if(e.select("img").size() == 0 && e.select("table").size() == 0 && StringUtils.isBlank(e.text())){
					e.remove();
				}
			}
			htmlStr = doc.html();
			htmlStr = htmlStr.replaceAll("\\n", "").replace(">  <", "><").replace("> <", "><");
	        return htmlStr;
		}catch(Exception e){
			return htmlStr;
		}
	}
}
