/*******************************************************************************
 * 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.wst.css.core.internal.text;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.wst.css.core.internal.Logger;
import org.eclipse.wst.css.core.internal.parser.CSSRegionUtil;
import org.eclipse.wst.css.core.internal.parserz.CSSRegionContexts;
import org.eclipse.wst.css.core.internal.util.CSSUtil;
import org.eclipse.wst.css.core.internal.util.RegionIterator;
import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextReParser;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.text.StructuredDocumentReParser;


/**
 * This class provides a centralized place to put "reparsing" logic. This is
 * the logic that reparses the text incrementally, as a user types in new
 * characters, or DOM nodes are inserted or deleted. Note: it is not a thread
 * safe class.
 */
public class CSSStructuredDocumentReParser extends StructuredDocumentReParser {

	class ReparseRange {
		ReparseRange() {
			reset();
		}

		ReparseRange(int start, int end) {
			fRangeStart = start;
			fRangeEnd = end;
		}

		void setStart(int start) {
			fRangeStart = start;
		}

		void setEnd(int end) {
			fRangeEnd = end;
		}

		int getStart() {
			return fRangeStart;
		}

		int getEnd() {
			return fRangeEnd;
		}

		boolean isValid() {
			return (0 < fRangeEnd - fRangeStart) ? true : false;
		}

		void reset() {
			fRangeStart = Integer.MAX_VALUE;
			fRangeEnd = 0;
		}

		void expand(ReparseRange range) {
			if (range == null || !range.isValid()) {
				return;
			}
			int start = range.getStart();
			if (start < fRangeStart) {
				fRangeStart = start;
			}
			int end = range.getEnd();
			if (fRangeEnd < end) {
				fRangeEnd = end;
			}
		}

		private int fRangeStart;
		private int fRangeEnd;
	}

	/**
	 * 
	 */
	public CSSStructuredDocumentReParser() {
		super();
	}

	/**
	 * 
	 */
	// public StructuredDocumentEvent
	// checkForCrossStructuredDocumentRegionBoundryCases2() {
	// StructuredDocumentEvent result = specialPositionUpdate(fStart, fStart +
	// fLengthToReplace - 1);
	// if (result == null) {
	// result = checkInsideBrace();
	// }
	// return result;
	// }
	protected StructuredDocumentEvent checkForCrossStructuredDocumentRegionSyntax() {
		int checkStart = fStart;
		int checkEnd = fStart + fLengthToReplace - 1;
		IStructuredDocumentRegion endRegion = fStructuredDocument.getRegionAtCharacterOffset(checkEnd);
		if (endRegion != null) {
			checkEnd = endRegion.getEndOffset();
		}

		ReparseRange range = new ReparseRange(checkStart, checkEnd);

		range.expand(getUpdateRangeForDelimiter(range.getStart(), range.getEnd()));
		range.expand(getUpdateRangeForUnknownRegion(range.getStart(), range.getEnd()));

		range.expand(getUpdateRangeForQuotes(range.getStart(), range.getEnd()));
		range.expand(getUpdateRangeForComments(range.getStart(), range.getEnd()));
		range.expand(getUpdateRangeForBraces(range.getStart(), range.getEnd()));

		StructuredDocumentEvent result;

		result = checkInsideBrace(range.getStart(), range.getEnd());

		if (result == null) {
			result = reparse(range.getStart(), range.getEnd());
		}

		return result;
	}

	private ReparseRange getUpdateRangeForUnknownRegion(int start, int end) {
		int newStart = start;
		RegionIterator iterator = new RegionIterator(fStructuredDocument, start - 1);
		if (iterator.hasPrev()) {
			iterator.prev(); // skip myself
		}
		while (iterator.hasPrev()) {
			ITextRegion region = iterator.prev();
			if (region != null && region.getType() == CSSRegionContexts.CSS_UNKNOWN) {
				newStart = iterator.getStructuredDocumentRegion().getStartOffset(region);
			}
			else {
				break;
			}
		}

		if (start != newStart) {
			return new ReparseRange(newStart, end);
		}

		return null;
	}

	private ReparseRange getUpdateRangeForDelimiter(int start, int end) {
		if (dirtyStart != null && dirtyStart.getStart() < start) {
			start = dirtyStart.getStart();
		}
		IStructuredDocumentRegion docRegion = fStructuredDocument.getRegionAtCharacterOffset(start);
		if (docRegion == null) {
			return null;
		}
		if (docRegion.getType() == CSSRegionContexts.CSS_DELIMITER) {
			IStructuredDocumentRegion prevRegion = docRegion.getPrevious();
			if (prevRegion != null) {
				return new ReparseRange(prevRegion.getStart(), end);
			}
		}

		return null;
	}

	private ReparseRange getUpdateRangeForQuotes(int start, int end) {
		ReparseRange range = new ReparseRange();

		range.expand(getUpdateRangeForPair(start, end, "\"", "\"")); //$NON-NLS-2$//$NON-NLS-1$
		range.expand(getUpdateRangeForPair(start, end, "\'", "\'")); //$NON-NLS-2$//$NON-NLS-1$

		return (range.isValid()) ? range : null;
	}

	private ReparseRange getUpdateRangeForComments(int start, int end) {
		ReparseRange range = new ReparseRange();

		range.expand(getUpdateRangeForPair(start, end, "/*", "*/")); //$NON-NLS-2$//$NON-NLS-1$
		range.expand(getUpdateRangeForPair(start, end, "<%", "%>")); //$NON-NLS-2$//$NON-NLS-1$

		return (range.isValid()) ? range : null;
	}

	private ReparseRange getUpdateRangeForBraces(int start, int end) {
		ReparseRange range = new ReparseRange();

		range.expand(getUpdateRangeForPair(start, end, "[", "]")); //$NON-NLS-2$//$NON-NLS-1$
		range.expand(getUpdateRangeForPair(start, end, "(", ")")); //$NON-NLS-2$//$NON-NLS-1$
		range.expand(getUpdateRangeForPair(start, end, "{", "}")); //$NON-NLS-2$//$NON-NLS-1$

		return (range.isValid()) ? range : null;
	}

	private StructuredDocumentEvent checkInsideBrace(int start, int end) {
		StructuredDocumentEvent result = null;
		IStructuredDocumentRegion region = fStructuredDocument.getRegionAtCharacterOffset(start);
		if (region == null) {
			return null;
		}
		boolean bDeclaration = false;
		String type = region.getType();
		if (CSSRegionUtil.isDeclarationType(type) || type == CSSRegionContexts.CSS_LBRACE || type == CSSRegionContexts.CSS_RBRACE) {
			bDeclaration = true;
		}
		if (!bDeclaration) {
			IStructuredDocumentRegion prevRegion = CSSUtil.findPreviousSignificantNode(region);
			if (prevRegion != null) {
				type = prevRegion.getType();
				if (CSSRegionUtil.isDeclarationType(type) || type == CSSRegionContexts.CSS_LBRACE) {
					bDeclaration = true;
				}
			}
		}
		if (!bDeclaration) {
			IStructuredDocumentRegion nextRegion = CSSUtil.findNextSignificantNode(region);
			if (nextRegion != null) {
				type = nextRegion.getType();
				if (CSSRegionUtil.isDeclarationType(type) || type == CSSRegionContexts.CSS_RBRACE) {
					bDeclaration = true;
				}
			}
		}

		if (bDeclaration) {
			IStructuredDocumentRegion startRegion = findRuleStart(region);
			if (startRegion != null) {
				IStructuredDocumentRegion endRegion = fStructuredDocument.getRegionAtCharacterOffset(end);
				if (endRegion != null) {
					result = reparse(startRegion, endRegion);
				}
			}
		}
		return result;
	}

	private IStructuredDocumentRegion findRuleStart(IStructuredDocumentRegion startRegion) {
		IStructuredDocumentRegion region = startRegion;
		// find '{'
		while (region != null && region.getType() != CSSRegionContexts.CSS_LBRACE) {
			region = region.getPrevious();
		}
		// if (region == startRegion) {
		// return null;
		// }
		// else
		if (region != null) { // '{' is found
			region = region.getPrevious();
			if (isLeadingDeclarationType(region.getType())) {
				return region;
			}
		}
		return null;
	}

	private boolean isLeadingDeclarationType(String type) {
		return (type == CSSRegionContexts.CSS_PAGE || type == CSSRegionContexts.CSS_FONT_FACE || CSSRegionUtil.isSelectorType(type));
	}

	// public StructuredDocumentEvent
	// checkForCrossStructuredDocumentRegionBoundryCases() {
	// return specialPositionUpdate(fStart, fStart + fLengthToReplace - 1);
	// }
	/**
	 * 
	 */
	private ReparseRange getUpdateRangeForPair(int start, int end, String opener, String closer) {
		StringBuffer deletionBuf = new StringBuffer();
		StringBuffer insertionBuf = new StringBuffer();
		int quoteLen = Math.max(opener.length(), closer.length());
		if (1 < quoteLen) {
			/**
			 * ex) opener = "ABC", closer = "XYZ" model: ABCDEF.......UVWXYZ
			 * deletion: CDEF.......UVWX pre/post: AB / YZ
			 */
			int addStart = start - (quoteLen - 1);
			if (0 <= addStart) {
				String addStr = fStructuredDocument.get(addStart, quoteLen - 1);
				deletionBuf.append(addStr);
				insertionBuf.append(addStr);
			}
			deletionBuf.append(fDeletedText);
			insertionBuf.append(fChanges);
			if (end + (quoteLen - 1) < fStructuredDocument.getLength()) {
				String addStr = fStructuredDocument.get(end + 1, quoteLen - 1);
				deletionBuf.append(addStr);
				insertionBuf.append(addStr);
			}
		}
		else {
			deletionBuf.append(fDeletedText);
			insertionBuf.append(fChanges);
		}
		String deletion = deletionBuf.toString();
		String insertion = insertionBuf.toString();

		int rangeStart = start;
		int rangeEnd = end;

		if (0 <= deletion.indexOf(opener) || 0 <= deletion.indexOf(closer) || 0 <= insertion.indexOf(opener) || 0 <= insertion.indexOf(closer)) {
			int s, e;
			try {
				if (start <= fStructuredDocument.getLength()) {
					IRegion startRegion = getFindReplaceDocumentAdapter().find(start - 1, opener, false, false, false, false);
					if (startRegion != null) {
						s = startRegion.getOffset();
					}
					else {
						s = -1;
					}
				}
				else {
					s = -1;
				}
				if (end < fStructuredDocument.getLength() - 1) {
					IRegion endRegion = getFindReplaceDocumentAdapter().find(end + 1, closer, true, false, false, false);
					if (endRegion != null) {
						e = endRegion.getOffset();
					}
					else {
						e = -1;
					}
				}
				else {
					e = -1;
				}
			}
			catch (BadLocationException ex) {
				Logger.logException(ex);
				return null;
			}
			if (0 <= s) {
				rangeStart = Math.min(rangeStart, s);
			}
			if (0 <= e) {
				rangeEnd = Math.max(rangeEnd, e);
			}
		}

		if (rangeStart < start || end < rangeEnd) {
			return new ReparseRange(rangeStart, rangeEnd);
		}
		else {
			return null;
		}
	}

	public IStructuredTextReParser newInstance() {
		return new CSSStructuredDocumentReParser();
	}
}