/*******************************************************************************
 * Copyright (c) 2001, 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.dtd.core.internal.parser;

import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;

import org.eclipse.wst.dtd.core.internal.text.DTDStructuredDocumentRegionFactory;
import org.eclipse.wst.dtd.core.internal.tokenizer.DTDTokenizer;
import org.eclipse.wst.dtd.core.internal.tokenizer.Token;
import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;


public class DTDRegionParser implements RegionParser {
	private Vector cachedRegions = null;
	private DTDTokenizer tokenizer = null;
	private IStructuredDocumentRegion cachedNode = null; // top of node
															// chain

	public RegionParser newInstance() {
		return new DTDRegionParser();
	}

	private IStructuredDocumentRegion addNewNodes(IStructuredDocumentRegion lastNode, Vector regions) {
		IStructuredDocumentRegion leadingSpaceNode = null;
		IStructuredDocumentRegion contentNode = null;
		IStructuredDocumentRegion trailingSpaceNode = null;
		LinkedList nodeSeeds = new LinkedList();
		int nRegions = regions.size();
		int leadingSpaceEnd = -1;
		int trailingSpaceBegin = nRegions;

		// find leading space
		nodeSeeds.clear();
		for (int i = 0; i < nRegions; i++) {
			ITextRegion region = (ITextRegion) regions.get(i);
			String type = region.getType();
			if (isBlankRegion(type)) {
				leadingSpaceEnd = i;
				nodeSeeds.addLast(region);
			}
			else {
				break;
			}
		}
		if (!nodeSeeds.isEmpty()) {
			leadingSpaceNode = createNode(nodeSeeds);
			if (lastNode != null) {
				lastNode.setNext(leadingSpaceNode);
				leadingSpaceNode.setPrevious(lastNode);
			}
			lastNode = leadingSpaceNode;
		}

		// find trailing space
		if (leadingSpaceEnd < nRegions - 1) {
			nodeSeeds.clear();
			for (int i = nRegions - 1; 0 <= i; i--) {
				ITextRegion region = (ITextRegion) regions.get(i);
				String type = ((ITextRegion) regions.get(i)).getType();
				if (isBlankRegion(type)) {
					trailingSpaceBegin = i;
					nodeSeeds.addFirst(region);
				}
				else {
					break;
				}
			}
			if (!nodeSeeds.isEmpty()) {
				trailingSpaceNode = createNode(nodeSeeds);
			}

			nodeSeeds.clear();
			for (int i = leadingSpaceEnd + 1; i < trailingSpaceBegin; i++) {
				nodeSeeds.addLast(regions.get(i));
			}
			if (!nodeSeeds.isEmpty()) {
				contentNode = createNode(nodeSeeds);
				if (lastNode != null) {
					lastNode.setNext(contentNode);
					contentNode.setPrevious(lastNode);
				}
				lastNode = contentNode;
			}
			if (trailingSpaceNode != null) {
				lastNode.setNext(trailingSpaceNode);
				trailingSpaceNode.setPrevious(lastNode);
				lastNode = trailingSpaceNode;
			}
		}

		return lastNode;
	}

	private IStructuredDocumentRegion createNode(LinkedList regions) {
		if (regions.size() == 0) {
			return null;
		}

		IStructuredDocumentRegion node = DTDStructuredDocumentRegionFactory.createStructuredDocumentRegion(DTDStructuredDocumentRegionFactory.DTD_GENERIC);
		int start = ((ITextRegion) regions.getFirst()).getStart();
		int length = ((ITextRegion) regions.getLast()).getEnd() - start;
		node.setStart(start);
		node.setLength(length);
		for (ListIterator i = regions.listIterator(0); i.hasNext();) {
			ITextRegion region = (ITextRegion) i.next();
			node.addRegion(region);
			region.adjustStart(-start);
		}
		node.setEnded(true);

		return node;
	}

	private IStructuredDocumentRegion createNodeChain(List regions) {
		IStructuredDocumentRegion headNode = null;
		IStructuredDocumentRegion lastNode = null;
		Vector nodeSeeds = new Vector();

		for (Iterator e = regions.iterator(); e.hasNext();) {
			ITextRegion region = (ITextRegion) e.next();
			String type = region.getType();
			// If the following regions appear,
			// a previous node is closed in front of it.
			if (!nodeSeeds.isEmpty() && isBeginningRegion(type)) {
				lastNode = addNewNodes(lastNode, nodeSeeds);
				nodeSeeds.clear();
			}
			nodeSeeds.addElement(region);

			// The following regions close the current node.
			if (!nodeSeeds.isEmpty() && isEndingRegion(type)) {
				lastNode = addNewNodes(lastNode, nodeSeeds);
				nodeSeeds.clear();
			}

			if (headNode == null && lastNode != null) {
				headNode = findFirstNode(lastNode);
			}
		}

		// close current node forcibly.
		if (!nodeSeeds.isEmpty()) {
			lastNode = addNewNodes(lastNode, nodeSeeds);
			if (headNode == null && lastNode != null) {
				headNode = findFirstNode(lastNode);
			}
		}
		return headNode;
	}

	private IStructuredDocumentRegion findFirstNode(IStructuredDocumentRegion node) {
		IStructuredDocumentRegion firstNode = node;
		IStructuredDocumentRegion prevNode = null;
		while ((prevNode = firstNode.getPrevious()) != null) {
			firstNode = prevNode;
		}
		return firstNode;
	}

	public IStructuredDocumentRegion getDocumentRegions() {
		if (cachedNode != null) {
			return cachedNode;
		}

		List regions = getRegions();
		IStructuredDocumentRegion headNode = createNodeChain(regions);
		cachedNode = headNode;

		return headNode;
	}

	public List getRegions() {
		if (cachedRegions != null) {
			return cachedRegions;
		}

		Vector regions = new Vector();
		Token currentToken = null;
		do {
			try {
				currentToken = (Token) tokenizer.yylex();
				if (currentToken != null) {
					ITextRegion region = DTDRegionFactory.createRegion(currentToken.getType(), currentToken.getStartOffset(), currentToken.getLength());
					regions.add(region);
				}
			}
			catch (java.io.FileNotFoundException e) {
				System.out.println("File not found"); //$NON-NLS-1$
			}
			catch (java.io.IOException e) {
				System.out.println("Error opening file"); //$NON-NLS-1$
			}
		}
		while (currentToken != null);

		cachedRegions = regions;
		return regions;
	}

	public void reset(Reader reader) {
		if (tokenizer == null) {
			try {
				tokenizer = new DTDTokenizer(reader);
			}
			catch (ArrayIndexOutOfBoundsException e) {
				System.out.println("Usage : java DTDTokenizer <inputfile>"); //$NON-NLS-1$
			}
		}
		else {
			try {
				tokenizer.yyreset(reader);
			}
			catch (java.io.IOException e) {
				System.out.println("Error opening file"); //$NON-NLS-1$
			}
		}

		cachedNode = null;
		cachedRegions = null;
	}

	/**
	 * An additional offset for use with any position-dependant parsing rules
	 */
	public void reset(Reader reader, int offset) {
		reset(reader);
	}

	public void reset(String input) {
		reset(new StringReader(input));
	}

	public void reset(String input, int offset) {
		reset(input);
	}

	// never used
	DTDTokenizer getTokenizer() {
		return tokenizer;
	}

	private boolean isBeginningRegion(String type) {
		return (type == DTDRegionTypes.START_TAG) || (type == DTDRegionTypes.ENTITY_PARM);
	}

	private boolean isBlankRegion(String type) {
		return (type == DTDRegionTypes.WHITESPACE);
	}

	private boolean isEndingRegion(String type) {
		return (type == DTDRegionTypes.END_TAG) || (type == DTDRegionTypes.ENTITY_PARM) || (type == DTDRegionTypes.COMMENT_END);
	}
}
