/*******************************************************************************
 * Copyright (c) 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.jsp.ui.tests.contentassist;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import junit.framework.TestCase;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.text.Position;
import org.eclipse.jst.jsp.core.internal.domdocument.DOMModelForJSP;
import org.eclipse.jst.jsp.core.internal.java.IJSPTranslation;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslation;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslationAdapter;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslationAdapterFactory;
import org.eclipse.jst.jsp.ui.tests.other.ScannerUnitTests;
import org.eclipse.jst.jsp.ui.tests.util.FileUtil;
import org.eclipse.jst.jsp.ui.tests.util.ProjectUnzipUtility;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;

/**
 * This class unit tests the sed JSPTranslation mechanism.
 * That includes JSPTranslationAdapterFactory, JSPTranslationAdapter, and JSPTranslation.
 * It uses the jsp_include_test.jsp, because of the more complicated translation and offsets.
 * 
 * @author pavery
 */
public class JSPTranslationTest extends TestCase {

	private ProjectUnzipUtility fProjUtil = null;
	private boolean isSetup = false;
	
	private HashMap fXMLJSPPositions;

	public JSPTranslationTest(String name) {
		super(name);
	}

	protected void setUp() throws Exception {
		super.setUp();
		if (!this.isSetup) {
			doSetup();
			this.isSetup = true;
		}
	}

	private void doSetup() throws Exception {
		fProjUtil = new ProjectUnzipUtility();

		// root of workspace directory
		Location platformLocation = Platform.getInstanceLocation();

		File zipFile = FileUtil.makeFileFor(ProjectUnzipUtility.PROJECT_ZIPS_FOLDER, "includes_tests.zip", ProjectUnzipUtility.PROJECT_ZIPS_FOLDER);
		fProjUtil.unzipAndImport(zipFile, platformLocation.getURL().getPath());
		fProjUtil.initJavaProject("INCLUDES_TESTS");
	}

	public void testTranslatePositions() {

		IDOMModel model = getIncludeTestModelForRead();
		JSPTranslationAdapter adapter = (JSPTranslationAdapter) model.getDocument().getAdapterFor(IJSPTranslation.class);
		JSPTranslation translation = adapter.getJSPTranslation();
		try {
			HashMap java2jsp = translation.getJava2JspMap();
			assertEquals("java2jsp map size:", 13, java2jsp.size());

			HashMap jsp2java = translation.getJsp2JavaMap();
			assertEquals("jsp2java map size:", 3, jsp2java.size());

			// some test positions (out.print("" + | );)
			
			// we need to ignore the classname length in our comparisons
			// with java offsets that we get from the translation
			// since it can vary depending on workspace location
			int classnameLength = translation.getClassname().length();
			
			int jspTestPosition = translation.getJspText().indexOf("<%= ") + 4;
			int javaOffset = translation.getJavaOffset(jspTestPosition) - classnameLength;
			assertEquals("JSPTranslation java offset:", 1009, javaOffset);
			
			// (<%= | %>)
			int javaTestPostition = translation.getJavaText().indexOf("out.print(\"\"+\n   \n);") + 14;
			// dont' need to worry about classname length here because we are comparing
			// with a position in the JSP document (which doesn't contain classname)
			int jspOffset = translation.getJspOffset(javaTestPostition);
			assertEquals("JSPTranslation jsp offset:", 564, jspOffset);
		}
		finally {
			if (model != null)
				model.releaseFromRead();
		}
	}


	public void testJSPTranslationText() {

		IDOMModel model = getIncludeTestModelForRead();
		ScannerUnitTests.verifyLengths(model, model.getStructuredDocument().get());
		JSPTranslationAdapter adapter = (JSPTranslationAdapter) model.getDocument().getAdapterFor(IJSPTranslation.class);
		JSPTranslation translation = adapter.getJSPTranslation();
		// named as .bin so no line conversion occurs (\n is in use)
		InputStream in = getClass().getResourceAsStream("translated_text.bin");
		String knownTranslationText = loadChars(in);
		try {
			// improvements: may need finer tuned text compares later
			// for different types of translations (includes, xml-jsp in script, attributes, etc...)
			String text = translation.getJavaText();
			
			assertNotNull("JSP translation text:", text);
			assertEquals("JSP translation text does not match expected", knownTranslationText, text);
		}
		finally {
			if (model != null)
				model.releaseFromRead();
		}
	}

	public void testJSPTranslationAdapter() {
		IDOMModel model = getIncludeTestModelForRead();
		JSPTranslationAdapter adapter = (JSPTranslationAdapter) model.getDocument().getAdapterFor(IJSPTranslation.class);
		JSPTranslation translation = adapter.getJSPTranslation();

		try {
			IJavaProject proj = adapter.getJavaProject();
			assertNotNull("couldn't get java project:" + proj);

			translation = adapter.getJSPTranslation();
			assertNotNull("couldn't get translation:", translation);
		}
		finally {
			if (model != null)
				model.releaseFromRead();
		}
	}

	/**
	 * Makes sure both beans are translated even though they are
	 * right next to each other with no space.
	 * 
	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=103004
	 */
	public void testUseBeanNoSpace() {
		IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path("INCLUDES_TESTS/useBean_tester.jsp"));
		DOMModelForJSP sModel = (DOMModelForJSP)getStructuredModelForRead(f);
		try {
			setupAdapterFactory(sModel);
			JSPTranslationAdapter adapter = (JSPTranslationAdapter) sModel.getDocument().getAdapterFor(IJSPTranslation.class);
			JSPTranslation translation = adapter.getJSPTranslation();
			String javaText = translation.getJavaText();
			boolean bean1 = javaText.indexOf("javax.swing.JButton x = null;") != -1;
			boolean bean2 = javaText.indexOf("javax.swing.JButton y = null;") != -1;
			assertTrue(bean1);
			assertTrue(bean2);
		}
		finally {
			if(sModel != null)
				sModel.releaseFromRead();
		}
	}
	
	/**
	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=86382
	 */
	public void testXMLJSPTranslationText() {
		IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path("INCLUDES_TESTS/xml-jsp/most-tags-xml-jsp.jsp"));
		DOMModelForJSP sModel = (DOMModelForJSP)getStructuredModelForRead(f);
		try {
			setupAdapterFactory(sModel);
			JSPTranslationAdapter adapter = (JSPTranslationAdapter) sModel.getDocument().getAdapterFor(IJSPTranslation.class);
			JSPTranslation translation = adapter.getJSPTranslation();
			
			String javaText = translation.getJavaText();
			
			// named as .bin so no line conversion occurs (\n is in use)
			InputStream in = getClass().getResourceAsStream("translated_xml_jsp.bin");
			String knownTranslationText = loadChars(in);
			
			assertEquals(knownTranslationText, javaText);
		}
		finally {
			if(sModel != null)
				sModel.releaseFromRead();
		}
	}
	
	public void testXMLJSPMapping() {
		IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path("INCLUDES_TESTS/xml-jsp/most-tags-xml-jsp.jsp"));
		DOMModelForJSP sModel = (DOMModelForJSP)getStructuredModelForRead(f);
		try {
			setupAdapterFactory(sModel);
			JSPTranslationAdapter adapter = (JSPTranslationAdapter) sModel.getDocument().getAdapterFor(IJSPTranslation.class);
			JSPTranslation translation = adapter.getJSPTranslation();
			
			HashMap jsp2java = translation.getJsp2JavaMap();
			Object[] jspRanges = jsp2java.keySet().toArray();
			Position jspPos = null;
			Position javaPos = null;
			for (int i = 0; i < jspRanges.length; i++) {
				jspPos = (Position)jspRanges[i];
				javaPos = (Position)jsp2java.get(jspPos);
				//System.out.println("jsp:" + printPos(jspPos) + " >> java:" + printPos(javaPos));
				checkPosition(jspPos, javaPos);
			}
		}
		finally {
			if(sModel != null)
				sModel.releaseFromRead();
		}
	}
	
	public void testXMLJSPCDATAText() {
		IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path("INCLUDES_TESTS/cdata/cdata.jsp"));
		DOMModelForJSP sModel = (DOMModelForJSP)getStructuredModelForRead(f);
		try {
			setupAdapterFactory(sModel);
			JSPTranslationAdapter adapter = (JSPTranslationAdapter) sModel.getDocument().getAdapterFor(IJSPTranslation.class);
			JSPTranslation translation = adapter.getJSPTranslation();
			
			String transText = translation.getJavaText();
			
//			 named as .bin so no line conversion occurs (\n is in use)
			InputStream in = getClass().getResourceAsStream("translated_xml_jsp_cdata.bin");
			String knownText = loadChars(in);
			
			assertEquals(knownText, transText);
		}
		finally {
			if(sModel != null)
				sModel.releaseFromRead();
		}
	}
	
	private void checkPosition(Position jspPos, Position javaPos) {
		
		HashMap expected = getXMLJSPPositions();
		Object[] keys =expected.keySet().toArray();
		Position expectedJspPos= null;
		Position expectedJavaPos = null;
		boolean found = false;
		for (int i = 0; i < keys.length; i++) {
			expectedJspPos = (Position)keys[i];
			if(jspPos.equals(expectedJspPos)) {
				expectedJavaPos = (Position)expected.get(expectedJspPos);
				found = true;
			}
		}
		assertTrue("expected JSP position missing: " + jspPos, found);
		assertNotNull("no expected java position for jspPos: " + printPos(jspPos), expectedJavaPos);
		assertEquals("unexpected java position was:" + printPos(javaPos) + " but expected:" + printPos(expectedJavaPos), javaPos, expectedJavaPos);
	}
	private String printPos(Position pos) {
		return pos != null ? "[" + pos.offset +":"+ pos.length + "]" : "null";
	}
	private HashMap getXMLJSPPositions() {
		if(fXMLJSPPositions == null) {
			fXMLJSPPositions = new HashMap();
			fXMLJSPPositions.put(new Position(882,52), new Position(920,31));
			fXMLJSPPositions.put(new Position(961,7), new Position(952,7));
			fXMLJSPPositions.put(new Position(1018,14), new Position(89,14));
			fXMLJSPPositions.put(new Position(640,2), new Position(888,2));
			fXMLJSPPositions.put(new Position(406,24), new Position(759,24));
			fXMLJSPPositions.put(new Position(685,19), new Position(897,19));
			fXMLJSPPositions.put(new Position(650,26), new Position(861,26));
			fXMLJSPPositions.put(new Position(563,9), new Position(848,9));
			fXMLJSPPositions.put(new Position(461,23), new Position(784,23));
			fXMLJSPPositions.put(new Position(522,8), new Position(822,8));
			fXMLJSPPositions.put(new Position(323,44), new Position(274,45));
			fXMLJSPPositions.put(new Position(245,43), new Position(229,44));
		}
		return fXMLJSPPositions;
	}
	
	private static String loadChars(InputStream input) {

		StringBuffer s = new StringBuffer();
		try {
			int c = -1;
			while ((c = input.read()) >= 0) {
				if (c > 255)
					break;
				s.append((char) c);
			}
			input.close();
		}
		catch (IOException e) {
			System.out.println("An I/O error occured while loading :");
			System.out.println(e);
		}
		return s.toString();
	}
	
	/**
	 * add the factory for JSPTranslationAdapter here
	 * @param sm
	 */
	private void setupAdapterFactory(IStructuredModel sm) {
		JSPTranslationAdapterFactory factory = new JSPTranslationAdapterFactory();
		sm.getFactoryRegistry().addFactory(factory);
	}

	/**
	 * IMPORTANT - release model (model.releaseFromRead()) after use
	 * @param file
	 * @return
	 */
	private IStructuredModel getStructuredModelForRead(IFile file) {
		try {
			IModelManager modelManager = StructuredModelManager.getModelManager();
			return modelManager.getModelForRead(file);
		}
		catch (IOException ioex) {
			System.out.println("couldn't open file > " + file);
		}
		catch (CoreException e) {
			e.printStackTrace();
		}
		return null;
	}

	private IDOMModel getIncludeTestModelForRead() {

		IPath jspTestFilePath = new Path("INCLUDES_TESTS/jsp_include_test.jsp");
		IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(jspTestFilePath);
		IDOMModel xmlModel = (IDOMModel) getStructuredModelForRead(file);
		setupAdapterFactory(xmlModel);
		return xmlModel;
	}
}