/*******************************************************************************
 * 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.internal.reconcile;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcilableModel;
import org.eclipse.jface.text.reconciler.IReconcileResult;
import org.eclipse.jface.text.reconciler.IReconcileStep;
import org.eclipse.jst.jsp.core.internal.java.ELProblem;
import org.eclipse.jst.jsp.core.internal.java.IJSPTranslation;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslationAdapter;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslationExtension;
import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.core.internal.util.StringUtils;
import org.eclipse.wst.sse.ui.internal.reconcile.DocumentAdapter;
import org.eclipse.wst.sse.ui.internal.reconcile.ReconcileAnnotationKey;
import org.eclipse.wst.sse.ui.internal.reconcile.StructuredReconcileStep;
import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;

/**
 * Creates a JSPTranslation for use w/ the JavaReconcileStep. Adapts Java
 * error positions to the JSP positions.
 * 
 * @author pavery
 */
public class ReconcileStepForJspTranslation extends StructuredReconcileStep {

	/**
	 * This contains is the translated java document. We create this here,
	 * then set it as the model on the next step, ReconcileStepForJava
	 */
	private JSPTranslationWrapper fModel = null;
	private IReconcileResult[] EMPTY_RECONCILE_RESULT_SET = new IReconcileResult[0];
	private JSPTranslationAdapter fTranslationAdapter = null;
	private JSPTranslationExtension fJSPTranslation = null;
	private static final boolean DEBUG = false;
	
	public ReconcileStepForJspTranslation(IReconcileStep step) {
		super(step);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.reconciler.AbstractReconcileStep#reconcileModel(org.eclipse.jface.text.reconciler.DirtyRegion,
	 *      org.eclipse.jface.text.IRegion)
	 */
	protected IReconcileResult[] reconcileModel(DirtyRegion dirtyRegion, IRegion subRegion) {

		if(DEBUG)
            System.out.println("[trace reconciler] > translating JSP in JSP TRANSLATE step"); //$NON-NLS-1$	

		if (isCanceled() || dirtyRegion == null)
			return EMPTY_RECONCILE_RESULT_SET;

		// create java model for java reconcile
		JSPTranslationAdapter adapter = getJSPTranslationAdapter();
		fJSPTranslation = adapter.getJSPTranslation();
		fModel = new JSPTranslationWrapper(fJSPTranslation);

		if(DEBUG)
            System.out.println("[trace reconciler] > JSP TRANSLATE step done"); //$NON-NLS-1$	
		
		//return EMPTY_RECONCILE_RESULT_SET;
		return adaptELProblems();
	}

	private IReconcileResult[] adaptELProblems() {
		List problems = fJSPTranslation.getELProblems();
		TemporaryAnnotation[] annotations = new TemporaryAnnotation[problems.size()];
			for (int i = 0; i < problems.size(); i++) {
				annotations[i] = createTemporaryAnnotationFromProblem((ELProblem) problems.get(i));
			}
			return annotations;
	}

	private TemporaryAnnotation createTemporaryAnnotationFromProblem(ELProblem problem) {
		IStructuredDocument sDoc = (IStructuredDocument) ((DocumentAdapter) getInputModel()).getDocument();
		String type = TemporaryAnnotation.ANNOT_ERROR;
		ReconcileAnnotationKey key = null;
		key = createKey(sDoc.getRegionAtCharacterOffset(problem.getPosition().getOffset()), ReconcileAnnotationKey.TOTAL);
		TemporaryAnnotation annotation = new TemporaryAnnotation(problem.getPosition(), type, problem.getMessage(), key);
		annotation.setAdditionalFixInfo(problem);
		return annotation;
	}

	/**
	 * @return
	 */
	private JSPTranslationAdapter getJSPTranslationAdapter() {
		if (fTranslationAdapter == null) {
			IReconcilableModel reconcilableModel = getInputModel();
			IDocument doc = null;

			if (reconcilableModel instanceof DocumentAdapter)
				doc = ((DocumentAdapter) reconcilableModel).getDocument();

			if (doc != null) {
				IStructuredModel model = null;
				try {
					model = StructuredModelManager.getModelManager().getExistingModelForRead(doc);
					if (model != null) {
						IDOMDocument xmlDoc = ((IDOMModel) model).getDocument();
						fTranslationAdapter = (JSPTranslationAdapter) xmlDoc.getAdapterFor(IJSPTranslation.class);
					}
				}
				finally {
					if (model != null)
						model.releaseFromRead();
				}
			}
		}
		return fTranslationAdapter;
	}

	public IReconcilableModel getModel() {
		return fModel;
	}

	/*
	 * @see org.eclipse.text.reconcilerpipe.AbstractReconcilePipeParticipant#convertToInputModel(org.eclipse.text.reconcilerpipe.IReconcileResult[])
	 */
	protected IReconcileResult[] convertToInputModel(IReconcileResult[] inputResults) {

		if (inputResults == null)
			return null;

		HashMap java2jspRanges = fJSPTranslation.getJava2JspMap();
		for (int i = 0; i < inputResults.length; i++) {
			if (isCanceled())
				return EMPTY_RECONCILE_RESULT_SET;
			if (!(inputResults[i] instanceof TemporaryAnnotation))
				continue;
			TemporaryAnnotation result = (TemporaryAnnotation) inputResults[i];
			adaptJava2JspPosition(result, java2jspRanges);
		}

		return inputResults;
	}

	/**
	 * @param pos
	 * @param java2jspRanges
	 */
	private void adaptJava2JspPosition(TemporaryAnnotation annotation, HashMap java2jspRanges) {
		Position pos = annotation.getPosition();
		int javaOffset = pos.offset;
		int offsetInRange = 0;
		Position jspPos, javaPos = null;
		boolean found = false;

		// iterate all mapped java ranges
		Iterator it = java2jspRanges.keySet().iterator();
		while (it.hasNext()) {
			javaPos = (Position) it.next();
			if (!javaPos.includes(javaOffset))
				continue;

			offsetInRange = javaOffset - javaPos.offset;
			jspPos = (Position) java2jspRanges.get(javaPos);
			if (jspPos != null) {
				pos.offset = jspPos.offset + offsetInRange;
				found = true;
				additionalPositionAdjustment(annotation, jspPos);
			}
			break;
		}
		// hide unmapped errors
		if (!found) {
			pos.offset = -1;
			pos.length = 0;
		}
	}

	/**
	 * Adjusts java position to JSP position for ranges that don't map
	 * "exactly". eg. <%@include file=""%>, <jsp:useBean/>, <%@import
	 * src=""%>...
	 * 
	 * @param pos
	 * @param jspPos
	 */
	private void additionalPositionAdjustment(TemporaryAnnotation annotation, Position jspPos) {
		Position pos = annotation.getPosition();
		IStructuredDocument sDoc = null;
		IStructuredDocumentRegion sdRegion = null;
		// analyze the sdRegion to see if it's import, expression, include
		ITextRegionList regions = null;
		ITextRegion r = null;
		String tagName = ""; //$NON-NLS-1$

		sDoc = (IStructuredDocument) ((DocumentAdapter) getInputModel()).getDocument();
		sdRegion = sDoc.getRegionAtCharacterOffset(jspPos.offset);
		// analyze the sdRegion to see if it's import, expression, include,
		// useBean...
		regions = sdRegion.getRegions();
		for (int i = 0; i < regions.size(); i++) {
			r = regions.get(i);
			if (r.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME || r.getType() == DOMRegionContext.XML_TAG_NAME) {
				tagName = sdRegion.getText(r).trim();
				if (tagName.equals("include")) { //$NON-NLS-1$
					adjustForInclude(annotation, pos, sdRegion, regions, i);
				}
				else if (tagName.equals("page")) { //$NON-NLS-1$
					adjustForPage(annotation, pos, sdRegion, regions, i);
				}
				else if (tagName.equals("jsp:useBean")) { //$NON-NLS-1$
					//adjustForUseBean(pos, sdRegion, regions, i);
					// do nothing for usebean for now...
					break;
				}
                // this can actually cause the WRONG node to be underlined
                // esp in the case of embedded attr regions
//				else {
//					// catch all for all other cases for now, at least we'll
//					// get
//					// the squiggle in the general area of the problem instead
//					// of some random place
//					pos.offset = sdRegion.getStartOffset(r);
//					pos.length = 1;
//					break;
//				}
			}
		}
	}

	private void adjustForInclude(TemporaryAnnotation annotation, Position pos, IStructuredDocumentRegion sdRegion, ITextRegionList regions, int startingRegionNumber) {
		ITextRegion r;
		String tagName;
		String noQuotes;
		for (int j = startingRegionNumber; j < regions.size(); j++) {
			r = regions.get(j);
			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME && !sdRegion.getText(r).trim().equals("file")) //$NON-NLS-1$
				// there's only one attribute allowed for <@include
				break;
			else if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
				tagName = sdRegion.getText(r).trim();
				noQuotes = StringUtils.strip(tagName);
				pos.offset = sdRegion.getStartOffset(r) + ((tagName.length() - noQuotes.length()) == 2 ? 1 : 0);
				pos.length = noQuotes.length();
				annotation.setText(annotation.getText() + " (in file: \"" + noQuotes + "\")"); //$NON-NLS-1$ //$NON-NLS-2$
				break;
			}
		}
	}

	private void adjustForPage(TemporaryAnnotation annotation, Position pos, IStructuredDocumentRegion sdRegion, ITextRegionList regions, int startingRegionNumber) {
		ITextRegion r;
		String value;
		int size = regions.size();

		for (int j = startingRegionNumber; j < size; j++) {
			r = regions.get(j);
			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME && sdRegion.getText(r).trim().equals("import")) { //$NON-NLS-1$
				if (size > j + 2) {
					r = regions.get(j + 2);
					if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
						value = sdRegion.getText(r);
						pos.offset = sdRegion.getStartOffset(r);
						pos.length = value.trim().length();
						annotation.setText(annotation.getText() + " (in file: \"" + StringUtils.stripQuotes(value) + "\")"); //$NON-NLS-1$ //$NON-NLS-2$
						break;
					}
				}
			}
		}
	}

	public void release() {
		if (fTranslationAdapter != null) {
			if(DEBUG) {
				System.out.println("ReconcileStepForJSPTranslation ["+this+"] releasing JSPTranslationAdapter " + fTranslationAdapter); //$NON-NLS-1$ //$NON-NLS-2$
			}
			fTranslationAdapter.release();
		}
		super.release();
	}
    
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.reconciler.IReconcileStep#setInputModel(org.eclipse.jface.text.reconciler.IReconcilableModel)
	 */
	public void setInputModel(IReconcilableModel inputModel) {
		// force to rebuild translation
		fTranslationAdapter = null;
		if (DEBUG) {
			System.out.println("======================================"); //$NON-NLS-1$
			System.out.println("setting input model" + inputModel); //$NON-NLS-1$
			System.out.println("======================================"); //$NON-NLS-1$
		}
		super.setInputModel(inputModel);
		
		reinitTranslationAdapter(inputModel);
	}

	/**
	 * @param inputModel
	 */
	private void reinitTranslationAdapter(IReconcilableModel inputModel) {

		IDocument doc = null;
		if (inputModel instanceof DocumentAdapter)
			doc = ((DocumentAdapter) inputModel).getDocument();

		if (doc != null) {
			IStructuredModel model = null;
			try {
				model = StructuredModelManager.getModelManager().getExistingModelForRead(doc);
				if(getJSPTranslationAdapter() != null)
					getJSPTranslationAdapter().setXMLModel((IDOMModel) model);
			}
			finally {
				if (model != null)
					model.releaseFromRead();
			}
		}
	}
}