package org.eclipse.gendoc.services.openoffice.test;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.gendoc.document.parser.documents.Unzipper;
import org.eclipse.gendoc.document.parser.documents.XMLParser;
import org.eclipse.gendoc.document.parser.documents.openoffice.OpenOfficeNamespaceContext;
import org.junit.Assert;
import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import junit.framework.TestCase;

public class OpenOfficeVerifyHelper {
	public OpenOfficeVerifyHelper(String filePath, OpenOfficeNamespaceContext namespaceContext) throws IOException, ParserConfigurationException {
		this.filePath = filePath; 
		this.namespaceContext = namespaceContext;
		unzipper = new Unzipper(new File(filePath));
		unzipper.unzip();

		xpath = XPathFactory.newInstance().newXPath();
		xpath.setNamespaceContext(namespaceContext);
		
		parsers = new HashMap<String, XMLParser>();
		try {
			verifyXmls(URIUtil.toFile(URIUtil.toURI(FileLocator.resolve(new URL(
					 "platform:/plugin/org.eclipse.gendoc.services.openoffice.test/resources/schemas")))));
		} catch (URISyntaxException e) {
			throw new IllegalArgumentException(e);
		}
	}
	
	public void dispose() {
		if (unzipper != null) {
			unzipper.clean();
			unzipper = null;
		}
	}
	
	public void verifyXmls(final File schemasLoc) throws ParserConfigurationException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setValidating(true);
		factory.setNamespaceAware(true);
		factory.setXIncludeAware(true);
		factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", 
				"http://www.w3.org/2001/XMLSchema");
		factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", 
				schemasLoc.list(new FilenameFilter() {
					@Override
					public boolean accept(File dir, String name) {
						return name.endsWith(".xsd");
					}
				}));				
		DocumentBuilder builder = factory.newDocumentBuilder();
		builder.setEntityResolver(new EntityResolver() {			
			@Override
			public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
				File f = null;
				if (systemId != null) {
					int index = systemId.lastIndexOf('/');
					if (index >= 0)
						f = new File(schemasLoc,systemId.substring(index+1));
					else
						f = new File(schemasLoc,systemId);
				} else { 			 					
					return null;
				}
				
				return new InputSource(new FileInputStream(f));
			}
		});
		
		builder.setErrorHandler(new ErrorHandler() {			
			@Override
			public void warning(SAXParseException exception) throws SAXException {
				warnings.add(exception);
			}
			
			@Override
			public void fatalError(SAXParseException exception) throws SAXException {
				errors.add(exception);
			}
			
			@Override
			public void error(SAXParseException exception) throws SAXException {
				errors.add(exception);
			}
		});
		verifyXmlsImpl(unzipper.getUnzipDocumentFile(), builder);
	}
	
	private void verifyXmlsImpl(File dir, DocumentBuilder builder) {
		File[] files = dir.listFiles(new FileFilter() {			
			@Override
			public boolean accept(File pathname) {
				return pathname.isDirectory() || 
					   pathname.getName().endsWith(".xml") ||
					   pathname.getName().equals(".xml.rels");
			}
		});
		
		if (files == null)
			return;
		
		for (File f : files) {
			String relPath = f.getPath().replace(
					unzipper.getUnzipDocumentFile().getPath(), "").
					replace(File.separator, "/");
			if (f.isDirectory()) {
				verifyXmlsImpl(f, builder);
			} else {			
				if (relPath.endsWith("revisionInfo.xml"))
					continue;
				try {
					InputStream in = new FileInputStream(f);
					warnings = new ArrayList<SAXException>();
					errors = new ArrayList<SAXException>();
					Document doc = builder.parse(new InputSource(in));
					filterErrorsFromIgnorablesNS(doc,errors);
					TestCase.assertEquals("XML parsing errors '"+relPath+"': " + Arrays.toString(errors.toArray()), 0, errors.size());
					TestCase.assertEquals("XML parsing warnings: '"+relPath+"'" + Arrays.toString(warnings.toArray()), 0, warnings.size());
				} catch (Exception e) {				
					TestCase.fail(String.format("Fail verifying Open Office content '%s': %s",relPath, e.getMessage()));
				}
			}			
		}
	}
	
	private void filterErrorsFromIgnorablesNS(Document doc, List<SAXException> errors) {
		if (errors.isEmpty())
			return;
		String text = doc.getDocumentElement().getAttributeNS("http://schemas.openxmlformats.org/markup-compatibility/2006","Ignorable");
		if (text.isEmpty())
			text = "";
		String[] ignorables = ("xml mc "+text).split(" ");  
		for (int i=0; i<ignorables.length; i++) {
			Iterator<SAXException> it = errors.iterator();
			while (it.hasNext()) {
				SAXException e = it.next();
				String str = e.getMessage();
				Pattern p = Pattern.compile("\\'"+ignorables[i]+"[a-zA-Z0-9]*\\:");
				Matcher m = p.matcher(str);
				if (m.find()) {
					it.remove();
				}
			}
		}
	}
	
	public void verifyEqual(String message, String file, String reg, String expected) {
		try {
			verify(message, 0, file, reg, expected);
		} catch (XPathExpressionException e) {
			throw new IllegalArgumentException(e);
		}
	}
	
	public void verifyNotEqual(String message, String file, String reg, String expected) {
		try {
			verify(message, 1, file, reg, expected);
		} catch (XPathExpressionException e) {
			throw new IllegalArgumentException(e);
		}
	}

	public void verifyNull(String message, String file, String reg) {
		try {
			verify(message, 2, file, reg, null);
		} catch (XPathExpressionException e) {
			throw new IllegalArgumentException(e);
		}		
	}
	
	public void verifyNotNull(String message, String file, String reg) {
		try {
			verify(message, 3, file, reg, null);
		} catch (XPathExpressionException e) {
			throw new IllegalArgumentException(e);
		}		
	}
	
	private void verify(String message, int op, String file, String reg, Object expected) throws XPathExpressionException {
		XMLParser parser = parsers.get(file);
		if (parser == null) {
			parser = new XMLParser(new File(unzipper.getUnzipDocumentFile(),file));
			parsers.put(file,parser);
		}
			
		Object value = (expected instanceof String) ? 
				xpath.evaluate(reg, parser.getDocument()).trim() :
				xpath.evaluate(reg, parser.getDocument(), XPathConstants.NODE);
				
		switch (op) {
			case 0:
				Assert.assertEquals(message,expected,value); 
				break;
			case 1:
				Assert.assertNotEquals(message,expected,value);
				break;
			case 2:
				Assert.assertNull(message,value);
				break;
			case 3:
				Assert.assertNotNull(message,value);
				break;
			default:
		}
		
	}
	
	private String filePath;
	private OpenOfficeNamespaceContext namespaceContext;
	private Unzipper unzipper;
	private XPath xpath;	
	private Map<String,XMLParser> parsers;
	
	private List<SAXException> warnings; 
	private List<SAXException> errors; 
}
