package org.docx4j.convert.out.XSLFO;

import java.io.File;
import java.util.List;

import javax.xml.bind.JAXBException;

import org.docx4j.XmlUtils;
import org.docx4j.convert.out.common.preprocess.ParagraphStylesInTableFix;
import org.docx4j.jaxb.Context;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.DocumentSettingsPart;
import org.docx4j.wml.Document;
import org.docx4j.wml.P;
import org.docx4j.wml.PPrBase.PStyle;
import org.docx4j.wml.Style;
import org.docx4j.wml.Styles;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * w:compatSetting[w:name="overrideTableStyleFontSizeAndJustification"]
 * is defined in [MS-DOCX] 
 * 
 * If this value is true, then the style hierarchy of the document is evaluated as specified 
 * in [ISO/IEC29500-1:2011] section 17.7.2.

	If this value is false, which is the default, then the following additional rules apply:
	
	If the default paragraph style (as specified in [ISO/IEC29500-1:2011] section 17.7.4.17) 
	specifies a font size of 11pt or 12pt, then that setting will not override the font size 
	specified by the table style for paragraphs in tables.
	
		// That's wrong; this additional rule only applies if the font size is 12pt (not 11pt!).
		// Tested in Word 2010 
	
	If the default paragraph style (as specified in [ISO/IEC29500-1:2011] section 17.7.4.17) 
	specifies a justification of left, then that setting will not override the justification 
	specified by the table style for paragraphs in tables.
	  
 * The philosophy seems to be that inside a table cell, Normal didn't apply.
 * 
 * NB: there are fairly comprehensive test cases in src/test/java
 * for the behaviour with font size (where in each case the expected
 * result is set on the basis of what Word does). There aren't any at the moment for
 * justification (which is assumed to follow the same logic we have here).
 * 
 * Where Normal is basedOn our DocDefaults style, Word *does* override the table style!
 * We'll ignore that for now, because the next version of docx4j (v3.3) 
 * stops creating a DocDefaults style. 
 */
public abstract class PStyleTableAbstract {
	
	protected static Logger log = LoggerFactory.getLogger(PStyleTableAbstract.class);	
	
	
	protected static boolean OVERRIDE;
	protected static int EXPECTED_RESULT;
	
//	protected static String STYLE_NAME = "Normal-TableGrid-BR";
	protected String getStyleName() {
		   return "Normal-TableGrid-BR";
	}
	
	static String styles_inRPrDefault;
	static String styles_inNormal;
	static String styles_inDefaultParagraphFont;
	static String styles_in_basedOn_Normal;
	static String styles_basedOn_Normal;
	static String styles_no_font_sz;

	static String table_styles;
	static String mdpXml_tblStyle;
	static String mdpXml_direct_12pt;	
	
	protected WordprocessingMLPackage test(String documentXml, String styleXml) throws Exception {
		return test( documentXml,  styleXml,  EXPECTED_RESULT);
	}
	
	protected WordprocessingMLPackage test(String documentXml, String styleXml,  int expectedResult) throws Exception {

		WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
		wordMLPackage.getMainDocumentPart().setContents(
				(Document)XmlUtils.unmarshalString(documentXml) );
		wordMLPackage.getMainDocumentPart().getStyleDefinitionsPart().setContents(
				(Styles)XmlUtils.unmarshalString(styleXml) );
		
		setSetting(wordMLPackage, OVERRIDE); 
		if (OVERRIDE) {
			log.info("table style should get overridden by Normal");
		} else {
			log.info("table style should NOT get overridden by Normal");			
		}

		/* Where Normal is basedOn our DocDefaults style,  
		 * Word *does* override the table style! 
		 * 
		 * It doesn't if there is just a normal DocDefaults element
		 * which sets the font size.  And that is what we should be testing here.
		 * 
		 * So save the docx
		 * 
		 * Note that createVirtualStylesForDocDefaults() puts 10pt there, if nothing is specified,
		 * so we save the docx here before that method has run.
		 * 
		 * TODO 2016 01 18 revisit this, since createVirtualStylesForDocDefaults has gone now
		 * (its only in StyleTree)
		 */
		wordMLPackage.save(new File(System.getProperty("user.dir") + "/OUT_PStyleInTableTest.docx"));
//		this.saveDocx(wordMLPackage, null);
		
		ParagraphStylesInTableFix.process(wordMLPackage);
				
//		// Now remove the style, and save the docx, to check in Word
//		Style s = getStyle(wordMLPackage, STYLE_NAME);
//		wordMLPackage.getMainDocumentPart().getStyleDefinitionsPart().getContents().getStyle().remove(s);
//		
//		getStyle(wordMLPackage, STYLE_NAME).setBasedOn(null);
//		
//		this.saveDocx(wordMLPackage, null);
		
		Style s = getStyle(wordMLPackage, getStyleName());

		if (s==null) {
			log.warn("missing style " + getStyleName());
			Assert.fail("missing style " + getStyleName());
		} else {		
			assertSz(s, expectedResult);
		}
		
		return wordMLPackage;
		
	}
	
	protected void assertSz(Style s, int expectedResult) {
		
		if (s.getRPr()!=null
				&& s.getRPr().getSz()!=null
				&& s.getRPr().getSz().getVal()!=null) {
			int actualResult = s.getRPr().getSz().getVal().intValue();
			Assert.assertTrue(actualResult==expectedResult);
		} else if (s.getRPr()!=null
				&& s.getRPr().getSz()==null) {
			log.warn("null Sz: " + XmlUtils.marshaltoString(s));
			Assert.fail("null Sz");
		}
		
	}

	protected void assertSzNull(Style s) {
		
		if (s.getRPr()==null) {
			
		} else if (s.getRPr()!=null) {
			
			Assert.assertNull(s.getRPr().getSz());
		}
		
	}
	
	
	protected void setSetting(WordprocessingMLPackage wmlPackage, boolean val) throws Docx4JException {
		
			DocumentSettingsPart dsp = wmlPackage.getMainDocumentPart().getDocumentSettingsPart();
			if (dsp==null) {
				dsp = new DocumentSettingsPart();
				wmlPackage.getMainDocumentPart().addTargetPart(dsp);
				
				dsp.setContents( Context.getWmlObjectFactory().createCTSettings() );
			} 

			if (val) {
				dsp.setWordCompatSetting("overrideTableStyleFontSizeAndJustification", "1");
			} else {
				dsp.setWordCompatSetting("overrideTableStyleFontSizeAndJustification", "0");				
			}
	}
	
	protected Style getStyle(WordprocessingMLPackage wordMLPackage, String stylename) throws Docx4JException {
		
		for (Style s : wordMLPackage.getMainDocumentPart().getStyleDefinitionsPart().getContents().getStyle()) {
			if (stylename.equals(s.getStyleId())) {
				return s;
			}
		}
		return null;
	}	
	
	void saveDocx(WordprocessingMLPackage wordMLPackage, String pStyle) throws Docx4JException, JAXBException {
		
		PStyle ps = null;
		if (pStyle!=null) {
			ps = Context.getWmlObjectFactory().createPPrBasePStyle();
			ps.setVal(pStyle);
		}
				
		List<Object> xpathResults = wordMLPackage.getMainDocumentPart().getJAXBNodesViaXPath("//w:p", true);
		((P)xpathResults.get(0)).getPPr().setPStyle(ps);
		
		wordMLPackage.save(new File(System.getProperty("user.dir") + "/OUT_PStyleInTableTest.docx"));
		
	}
	
	

	static void initOtherXml() {
		initOtherXml(24);
	}
	
	static void initOtherXml(int fontSizeHps) {

	styles_inRPrDefault = "<w:styles mc:Ignorable=\"w14\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\">"
	        + "<w:docDefaults>"
	              + "<w:rPrDefault>"
	                    + "<w:rPr>"
	                          + "<w:sz w:val=\"" + fontSizeHps + "\"/>"
	                          + "<w:szCs w:val=\"" + fontSizeHps + "\"/>"
	                    + "</w:rPr>"
	              + "</w:rPrDefault>"
	              + "<w:pPrDefault>"
	                    + "<w:pPr>"
	                          + "<w:spacing w:after=\"120\"/>"
	                    + "</w:pPr>"
	              + "</w:pPrDefault>"
	        + "</w:docDefaults>"
	        + "<w:style w:default=\"1\" w:styleId=\"Normal\" w:type=\"paragraph\">"
	              + "<w:name w:val=\"Normal\"/>"
	              + "<w:qFormat/>"
	              + "<w:rPr>"
	                    + "<w:rFonts w:ascii=\"Times New Roman\"/>"
	              + "</w:rPr>"
	        + "</w:style>"
	        + "<w:style w:default=\"1\" w:styleId=\"DefaultParagraphFont\" w:type=\"character\">"
	              + "<w:name w:val=\"Default Paragraph Font\"/>"
	              + "<w:uiPriority w:val=\"1\"/>"
	              + "<w:semiHidden/>"
	              + "<w:unhideWhenUsed/>"
	        + "</w:style>"
	        + table_styles
	  + "</w:styles>";

	styles_inNormal = "<w:styles mc:Ignorable=\"w14\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\">"
	        + "<w:docDefaults>"
	              + "<w:rPrDefault>"
	                    + "<w:rPr>"
	                    	+ "<w:color w:themeColor=\"accent1\" w:themeShade=\"BF\" w:val=\"365F91\"/>"
	                    + "</w:rPr>"
	              + "</w:rPrDefault>"
	              + "<w:pPrDefault>"
	                    + "<w:pPr>"
	                          + "<w:spacing w:after=\"120\"/>"
	                    + "</w:pPr>"
	              + "</w:pPrDefault>"
	        + "</w:docDefaults>"
	        + "<w:style w:default=\"1\" w:styleId=\"Normal\" w:type=\"paragraph\">"
	              + "<w:name w:val=\"Normal\"/>"
	              + "<w:qFormat/>"
	              + "<w:rPr>"
		              + "<w:sz w:val=\"" + fontSizeHps + "\"/>"
		              + "<w:szCs w:val=\"" + fontSizeHps + "\"/>"
	              + "</w:rPr>"
	        + "</w:style>"
	        + "<w:style w:default=\"1\" w:styleId=\"DefaultParagraphFont\" w:type=\"character\">"
	              + "<w:name w:val=\"Default Paragraph Font\"/>"
	              + "<w:uiPriority w:val=\"1\"/>"
	              + "<w:semiHidden/>"
	              + "<w:unhideWhenUsed/>"
	        + "</w:style>"
	        + table_styles
	  + "</w:styles>";

	styles_inDefaultParagraphFont = "<w:styles mc:Ignorable=\"w14\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\">"
	        + "<w:docDefaults>"
	              + "<w:rPrDefault>"
	                    + "<w:rPr>"
	                    	+ "<w:color w:themeColor=\"accent1\" w:themeShade=\"BF\" w:val=\"365F91\"/>"
	                    + "</w:rPr>"
	              + "</w:rPrDefault>"
	              + "<w:pPrDefault>"
	                    + "<w:pPr>"
	                          + "<w:spacing w:after=\"120\"/>"
	                    + "</w:pPr>"
	              + "</w:pPrDefault>"
	        + "</w:docDefaults>"
	        + "<w:style w:default=\"1\" w:styleId=\"Normal\" w:type=\"paragraph\">"
	              + "<w:name w:val=\"Normal\"/>"
	              + "<w:qFormat/>"
	        + "</w:style>"
	        + "<w:style w:default=\"1\" w:styleId=\"DefaultParagraphFont\" w:type=\"character\">"
	              + "<w:name w:val=\"Default Paragraph Font\"/>"
	              + "<w:uiPriority w:val=\"1\"/>"
	              + "<w:semiHidden/>"
	              + "<w:unhideWhenUsed/>"
	              + "<w:rPr>"
	            	+ "<w:sz w:val=\"" + fontSizeHps + "\"/>"
	            	+ "<w:szCs w:val=\"" + fontSizeHps + "\"/>"
	            + "</w:rPr>"
	        + "</w:style>"
	        + table_styles
	  + "</w:styles>";

	styles_in_basedOn_Normal = "<w:styles mc:Ignorable=\"w14\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\">"
	        + "<w:docDefaults>"
	              + "<w:rPrDefault>"
	                    + "<w:rPr>"
	                    	+ "<w:color w:themeColor=\"accent1\" w:themeShade=\"BF\" w:val=\"365F91\"/>"
	                    + "</w:rPr>"
	              + "</w:rPrDefault>"
	              + "<w:pPrDefault>"
	                    + "<w:pPr>"
	                          + "<w:spacing w:after=\"120\"/>"
	                    + "</w:pPr>"
	              + "</w:pPrDefault>"
	        + "</w:docDefaults>"
	        + "<w:style w:default=\"1\" w:styleId=\"Normal\" w:type=\"paragraph\">"
	              + "<w:name w:val=\"Normal\"/>"
	              + "<w:qFormat/>"
	              + "<w:rPr>"
	                    + "<w:rFonts w:ascii=\"Times New Roman\"/>"
	              + "</w:rPr>"
	        + "</w:style>"
	        + "<w:style w:styleId=\"testStyle\" w:type=\"paragraph\">"
	              + "<w:name w:val=\"testStyle\"/>"
	              + "<w:basedOn w:val=\"Normal\"/>"
	              + "<w:next w:val=\"Normal\"/>"
//	              + "<w:link w:val=\"Heading1Char\"/>"
	              + "<w:uiPriority w:val=\"9\"/>"
	              + "<w:qFormat/>"
	              + "<w:rsid w:val=\"00841CD9\"/>"
	              + "<w:pPr>"
	                    + "<w:keepNext/>"
	                    + "<w:keepLines/>"
	                    + "<w:spacing w:before=\"480\"/>"
	              + "</w:pPr>"
	              + "<w:rPr>"
	                    + "<w:rFonts w:asciiTheme=\"majorHAnsi\" w:cstheme=\"majorBidi\" w:eastAsiaTheme=\"majorEastAsia\" w:hAnsiTheme=\"majorHAnsi\"/>"
	                    + "<w:b/>"
	                    + "<w:bCs/>"
	                    + "<w:color w:themeColor=\"accent1\" w:themeShade=\"BF\" w:val=\"365F91\"/>"
	                    + "<w:sz w:val=\"" + fontSizeHps + "\"/>"
	                    + "<w:szCs w:val=\"" + fontSizeHps + "\"/>"
	              + "</w:rPr>"
	        + "</w:style>"
	        + "<w:style w:default=\"1\" w:styleId=\"DefaultParagraphFont\" w:type=\"character\">"
	              + "<w:name w:val=\"Default Paragraph Font\"/>"
	              + "<w:uiPriority w:val=\"1\"/>"
	              + "<w:semiHidden/>"
	              + "<w:unhideWhenUsed/>"
	        + "</w:style>"
	        + table_styles
	  + "</w:styles>";
		
	styles_basedOn_Normal = "<w:styles mc:Ignorable=\"w14\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\">"
	        + "<w:docDefaults>"
	              + "<w:rPrDefault>"
	                    + "<w:rPr>"
	                    	+ "<w:color w:themeColor=\"accent1\" w:themeShade=\"BF\" w:val=\"365F91\"/>"
	                    + "</w:rPr>"
	              + "</w:rPrDefault>"
	              + "<w:pPrDefault>"
	                    + "<w:pPr>"
	                          + "<w:spacing w:after=\"120\"/>"
	                    + "</w:pPr>"
	              + "</w:pPrDefault>"
	        + "</w:docDefaults>"
	        + "<w:style w:default=\"1\" w:styleId=\"Normal\" w:type=\"paragraph\">"
	              + "<w:name w:val=\"Normal\"/>"
	              + "<w:qFormat/>"
	              + "<w:rPr>"
		                  + "<w:rFonts w:asciiTheme=\"majorHAnsi\" w:cstheme=\"majorBidi\" w:eastAsiaTheme=\"majorEastAsia\" w:hAnsiTheme=\"majorHAnsi\"/>"
		                  + "<w:b/>"
		                  + "<w:bCs/>"
		                  + "<w:color w:themeColor=\"accent1\" w:themeShade=\"BF\" w:val=\"365F91\"/>"
		                  + "<w:sz w:val=\"" + fontSizeHps + "\"/>"
		                  + "<w:szCs w:val=\"" + fontSizeHps + "\"/>"
		            + "</w:rPr>"
	        + "</w:style>"
	        + "<w:style w:styleId=\"testStyle\" w:type=\"paragraph\">"
	              + "<w:name w:val=\"testStyle\"/>"
	              + "<w:basedOn w:val=\"Normal\"/>"
	              + "<w:next w:val=\"Normal\"/>"
//	              + "<w:link w:val=\"Heading1Char\"/>"
	              + "<w:uiPriority w:val=\"9\"/>"
	              + "<w:qFormat/>"
	              + "<w:rsid w:val=\"00841CD9\"/>"
	              + "<w:pPr>"
	                    + "<w:keepNext/>"
	                    + "<w:keepLines/>"
	                    + "<w:spacing w:before=\"480\"/>"
	              + "</w:pPr>"
	        + "</w:style>"
	        + "<w:style w:default=\"1\" w:styleId=\"DefaultParagraphFont\" w:type=\"character\">"
	              + "<w:name w:val=\"Default Paragraph Font\"/>"
	              + "<w:uiPriority w:val=\"1\"/>"
	              + "<w:semiHidden/>"
	              + "<w:unhideWhenUsed/>"
	        + "</w:style>"
	        + table_styles
	  + "</w:styles>";
	
	styles_no_font_sz = "<w:styles mc:Ignorable=\"w14\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\">"
	        + "<w:docDefaults>"
	              + "<w:rPrDefault>"
	                    + "<w:rPr>"
	                    	+ "<w:color w:themeColor=\"accent1\" w:themeShade=\"BF\" w:val=\"365F91\"/>"
	                    + "</w:rPr>"
	              + "</w:rPrDefault>"
	              + "<w:pPrDefault>"
	                    + "<w:pPr>"
	                          + "<w:spacing w:after=\"120\"/>"
	                    + "</w:pPr>"
	              + "</w:pPrDefault>"
	        + "</w:docDefaults>"
	        + "<w:style w:default=\"1\" w:styleId=\"Normal\" w:type=\"paragraph\">"
	              + "<w:name w:val=\"Normal\"/>"
	              + "<w:qFormat/>"
	        + "</w:style>"
	        + "<w:style w:default=\"1\" w:styleId=\"DefaultParagraphFont\" w:type=\"character\">"
	              + "<w:name w:val=\"Default Paragraph Font\"/>"
	              + "<w:uiPriority w:val=\"1\"/>"
	              + "<w:semiHidden/>"
	              + "<w:unhideWhenUsed/>"
	        + "</w:style>"
	        + table_styles
	  + "</w:styles>";
	
	
	}
	


	
	static void initTbls(boolean useTableGrid) {
		
		String styleId;

		if (useTableGrid) {
			styleId = "TableGrid";
			table_styles = 
					"<w:style w:default=\"1\" w:styleId=\"TableNormal\" w:type=\"table\">"
				        + "<w:name w:val=\"Normal Table\"/>"
				  + "</w:style>"
				  + "<w:style w:styleId=\"TableGrid\" w:type=\"table\">"
				        + "<w:name w:val=\"Table Grid\"/>"
				        + "<w:basedOn w:val=\"TableNormal\"/>"
				        + "<w:rPr>"
				            // Table style sets to 20pt
					        + "<w:sz w:val=\"40\"/>"
					        + "<w:szCs w:val=\"40\"/>"
					  + "</w:rPr>"
				  + "</w:style>";
		} else {
			styleId = "TableNormal";
			table_styles = 
					"<w:style w:default=\"1\" w:styleId=\"TableNormal\" w:type=\"table\">"
				        + "<w:name w:val=\"Normal Table\"/>"
				        + "<w:rPr>"
				            // Table style sets to 20pt
					        + "<w:sz w:val=\"40\"/>"
					        + "<w:szCs w:val=\"40\"/>"
					  + "</w:rPr>"
				  + "</w:style>";
			
		}
		
		mdpXml_tblStyle = "<w:document  xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" >" 
		        + "<w:body>"
		              + "<w:tbl>"
		                    + "<w:tblPr>"
		                          + "<w:tblStyle w:val=\"" + styleId + "\"/>"
		                    + "</w:tblPr>"
		                    + "<w:tr >"
		                          + "<w:tc>"
		                                + "<w:p>"
		                                      + "<w:r>"
		                                      + "<w:t xml:space=\"preserve\">some latin text here </w:t>"
		                                      + "</w:r>"
		                                + "</w:p>"
		                          + "</w:tc>"
		                    + "</w:tr>"
		              + "</w:tbl>"
		        + "</w:body>"
		  + "</w:document>";
		
		mdpXml_direct_12pt = "<w:document  xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" >" 
		        + "<w:body>"
		              + "<w:tbl>"
		                    + "<w:tblPr>"
	                          + "<w:tblStyle w:val=\"" + styleId + "\"/>"
		                    + "</w:tblPr>"
		                    + "<w:tr >"
		                          + "<w:tc>"
		                                + "<w:p>"
		                                      + "<w:r>"
		                                      	  // Direct formatting of 12pt
			                                      + "<w:rPr>"
				                                      + "<w:sz w:val=\"24\"/>"
				                                      + "<w:szCs w:val=\"24\"/>"
				                                + "</w:rPr>"
		                                      + "<w:t xml:space=\"preserve\">some latin text here </w:t>"
		                                      + "</w:r>"
		                                + "</w:p>"
		                          + "</w:tc>"
		                    + "</w:tr>"
		              + "</w:tbl>"
		        + "</w:body>"
		  + "</w:document>";
		

//	static String mdpXml_tblPr = "<w:document  xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" >" 
//	        + "<w:body>"
//	              + "<w:tbl>"
//	                    + "<w:tblPr>"
//			        	   + "<w:rPr><!-- Not valid -->"
//			    	            // Table style sets to 20pt
//			    		        + "<w:sz w:val=\"40\"/>"
//			    		        + "<w:szCs w:val=\"40\"/>"
//			    		  + "</w:rPr>"
//	                    + "</w:tblPr>"
//	                    + "<w:tr >"
//	                          + "<w:tc>"
//	                                + "<w:p>"
//	                                      + "<w:r>"
//	                                      + "<w:t xml:space=\"preserve\">some latin text here </w:t>"
//	                                      + "</w:r>"
//	                                + "</w:p>"
//	                          + "</w:tc>"
//	                    + "</w:tr>"
//	              + "</w:tbl>"
//	        + "</w:body>"
//	  + "</w:document>";


	
	}





}