/*******************************************************************************
 * 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;

import org.eclipse.swt.graphics.Image;
import org.eclipse.wst.dtd.core.internal.parser.DTDRegionTypes;
import org.eclipse.wst.dtd.core.internal.text.RegionIterator;
import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.text.ITextRegion;


// external node contains code to help set and get public ids
public class Entity extends ExternalNode {

	private static String setExternalEntity = DTDCorePlugin.getDTDString("_UI_LABEL_ENTITY_SET_EXT_ENTITY"); //$NON-NLS-1$
	private static String setGeneralEntity = DTDCorePlugin.getDTDString("_UI_LABEL_ENTITY_SET_GENERAL_ENTITY"); //$NON-NLS-1$
	private static String setInternalEntity = DTDCorePlugin.getDTDString("_UI_LABEL_ENTITY_SET_INT_ENTITY"); //$NON-NLS-1$

	private static String setParameterEntity = DTDCorePlugin.getDTDString("_UI_LABEL_ENTITY_SET_PARM_ENTITY"); //$NON-NLS-1$

	public Entity(DTDFile file, IStructuredDocumentRegion flatNode) {
		super(file, flatNode, DTDRegionTypes.ENTITY_TAG);
	}

	public Image getImage() {
		return DTDCorePlugin.getInstance().getImage(DTDResource.ENTITYICON);
	}


	/**
	 * Get the value of notationName.
	 * 
	 * @return value of notationName.
	 */
	public String getNotationName() {
		ITextRegion ndataRegion = getNextRegion(iterator(), DTDRegionTypes.NDATA_VALUE);
		if (ndataRegion != null) {
			return getStructuredDTDDocumentRegion().getText(ndataRegion);
		}
		return ""; //$NON-NLS-1$
	}

	public ITextRegion getPercentRegion() {
		return getNextRegion(iterator(), DTDRegionTypes.PERCENT);
	}

	/**
	 * Get the value of value.
	 * 
	 * @return value of value.
	 */
	public String getValue() {
		if (!isExternalEntity()) {
			ITextRegion valueRegion = getNextQuotedLiteral(iterator());
			if (valueRegion != null) {
				return getValueFromQuotedRegion(valueRegion);
			}
		}
		return ""; //$NON-NLS-1$
	}

	/**
	 * Get the value of externalEntity.
	 * 
	 * @return value of externalEntity.
	 */
	public boolean isExternalEntity() {
		return getPublicKeywordRegion(iterator()) != null || getSystemKeywordRegion(iterator()) != null;
	}

	/**
	 * Get the value of isParameterEntity.
	 * 
	 * @return value of isParameterEntity.
	 */
	public boolean isParameterEntity() {
		return getPercentRegion() != null;
	}

	private void removeNData(Object requestor) {
		ITextRegion ndataRegion = null;

		// see if we have an NDATA keyword
		ndataRegion = getNextRegion(iterator(), DTDRegionTypes.NDATA_KEYWORD);
		int startOffset = 0, endOffset = 0;
		if (ndataRegion != null) {
			startOffset = getStructuredDTDDocumentRegion().getStartOffset(ndataRegion);
			endOffset = getStructuredDTDDocumentRegion().getEndOffset(ndataRegion);
		}
		ITextRegion value = getNextRegion(iterator(), DTDRegionTypes.NDATA_VALUE);
		if (value != null) {
			if (startOffset == 0) {
				startOffset = getStructuredDTDDocumentRegion().getStartOffset(value);
			}
			endOffset = getStructuredDTDDocumentRegion().getEndOffset(value);
		}
		replaceText(requestor, startOffset, endOffset - startOffset, ""); //$NON-NLS-1$
	}

	/**
	 * Set the value of externalEntity.
	 * 
	 * @param v
	 *            Value to assign to externalEntity.
	 */
	public void setExternalEntity(boolean isExternalEntity) {
		if (isExternalEntity() != isExternalEntity) {
			// externalEntity = v;
			beginRecording(this, isExternalEntity ? setExternalEntity : setInternalEntity);
			if (isExternalEntity) {
				// we need to get rid of the value literal
				ITextRegion quote = getNextRegion(iterator(), DTDRegionTypes.SINGLEQUOTED_LITERAL);
				if (quote == null) {
					quote = getNextRegion(iterator(), DTDRegionTypes.DOUBLEQUOTED_LITERAL);
				}
				if (quote != null) {
					replaceText(this, getStructuredDTDDocumentRegion().getStartOffset(quote), quote.getLength(), ""); //$NON-NLS-1$
				}
				setSystemID(""); //$NON-NLS-1$
			}
			else {
				// we need to get rid of text between end of name region and
				// the last double quoted literal
				RegionIterator iter = iterator();
				ITextRegion keyword = getSystemKeywordRegion(iter);
				int startOffset = 0;
				int length = 0;
				if (keyword == null) {
					// reset the iterator
					iter = iterator();
					keyword = getPublicKeywordRegion(iter);
				}
				if (keyword != null) {
					startOffset = getStructuredDTDDocumentRegion().getStartOffset(keyword);
					// start with a length just equal to the keyword for now
					length = keyword.getLength();
				}
				else {
					// reset the iterator since we didn't find the keyword
					iter = iterator();
					// just go from after the name
					startOffset = getStructuredDTDDocumentRegion().getEndOffset(getNameRegion());
				}

				// now that we have the start, look for the end
				ITextRegion lastRegion = null;

				if (lastRegion == null) {
					// then look for last quoted literal
					while (iter.hasNext()) {
						ITextRegion literal = getNextQuotedLiteral(iter);
						if (literal != null) {
							lastRegion = literal;
						}
					}
				}

				if (lastRegion != null) {
					length = getStructuredDTDDocumentRegion().getEndOffset(lastRegion) - startOffset;
				}
				replaceText(this, startOffset, length, "\"\""); //$NON-NLS-1$
				removeNData(this);
			}
			endRecording(this);
		}
	}

	public void setNotationName(Object requestor, String newNotation) {
		if (!getNotationName().equals(newNotation)) {
			if (!newNotation.equals("")) { //$NON-NLS-1$
				// 
				ITextRegion ndataRegion = getNextRegion(iterator(), DTDRegionTypes.NDATA_VALUE);
				if (ndataRegion != null) {
					replaceText(requestor, getStructuredDTDDocumentRegion().getStartOffset(ndataRegion), ndataRegion.getLength(), newNotation);
				}
				else {
					// time to create one
					int startOffset = 0;
					String string = ""; //$NON-NLS-1$
					RegionIterator iter = iterator();
					ITextRegion ndataKeyword = getNextRegion(iter, DTDRegionTypes.NDATA_KEYWORD);
					if (ndataKeyword == null) {
						// we'll need to create one after the last quoted
						// literal
						// Reset iterator
						string += " NDATA "; //$NON-NLS-1$
						iter = iterator();
						ITextRegion lastQuotedLiteral = null;
						while (iter.hasNext()) {
							ITextRegion literal = getNextQuotedLiteral(iter);
							if (literal != null) {
								lastQuotedLiteral = literal;
							}
						}
						if (lastQuotedLiteral != null) {
							startOffset = getStructuredDTDDocumentRegion().getEndOffset(lastQuotedLiteral);
						}
						else {
							// created after the system or public keyword
							ITextRegion keyword = getPublicKeywordRegion(iterator());
							if (keyword == null) {
								keyword = getSystemKeywordRegion(iterator());
							}
							// we shouldn't be null here since we check if we
							// were external already
							startOffset = getStructuredDTDDocumentRegion().getEndOffset(keyword);
						}

					}
					else {
						startOffset = getStructuredDTDDocumentRegion().getEndOffset(ndataKeyword);
					}
					replaceText(requestor, startOffset, 0, string + newNotation);
				}
			}
			else {
				// need to remove the ndata stuff
				removeNData(requestor);
			}
		}
	}

	/**
	 * Set the value of notationName.
	 * 
	 * @param newNotation
	 *            Value to assign to notationName.
	 */
	public void setNotationName(String newNotation) {
		beginRecording(this, "NDATA " + DTDCorePlugin.getDTDString("_UI_LABEL_ENTITY_NDATA_CHANGE")); //$NON-NLS-1$ //$NON-NLS-2$
		setNotationName(this, newNotation);
		endRecording(this);
	}

	/**
	 * Set the value of isParameterEntity.
	 * 
	 * @param v
	 *            Value to assign to isParameterEntity.
	 */
	public void setParameterEntity(boolean v) {
		if (isParameterEntity() != v) {
			beginRecording(this, v ? setParameterEntity : setGeneralEntity);
			if (v) {
				RegionIterator iter = iterator();
				ITextRegion startTag = getNextRegion(iter, DTDRegionTypes.ENTITY_TAG);
				int startOffset = 0, length = 0;

				if (iter.hasNext()) {
					ITextRegion region = iter.next();
					startOffset = getStructuredDTDDocumentRegion().getStartOffset(region);
					if (region.getType() == DTDRegionTypes.WHITESPACE && region.getLength() > 1) {
						length = 1;
					}
				}
				else {
					startOffset = getStructuredDTDDocumentRegion().getEndOffset(startTag);
				}
				replaceText(this, startOffset, length, " %"); //$NON-NLS-1$
				// now get rid of any NData since it is only allowed if the
				// entity is a general entity and not a parameter entity
				removeNData(this);
			}
			else {
				// get rid of percent region
				ITextRegion percentRegion = getPercentRegion();
				replaceText(this, getStructuredDTDDocumentRegion().getStartOffset(percentRegion), percentRegion.getLength(), ""); //$NON-NLS-1$
			}

			endRecording(this);
		}
	}

	/**
	 * Set the value of value.
	 * 
	 * @param v
	 *            Value to assign to value.
	 */
	public void setValue(Object requestor, String v) {
		if (!isExternalEntity()) {
			if (!getValue().equals(v)) {
				// then it makes sense to change the value
				ITextRegion valueRegion = getNextQuotedLiteral(iterator());
				String quoteChar = v.indexOf("\"") == -1 ? "\"" : "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				if (valueRegion != null) {
					replaceText(requestor, getStructuredDTDDocumentRegion().getStartOffset(valueRegion), valueRegion.getLength(), quoteChar + v + quoteChar);
				}
				else {
					int startOffset = 0;
					RegionIterator iter = iterator();
					ITextRegion region = getNextRegion(iter, DTDRegionTypes.NAME);
					if (region == null) {
						// create it after the percent if there is one
						region = getPercentRegion();
					}
					if (region == null) {
						// if still null, then create it after the element tag
						region = getStartTag(iterator());
					}

					if (region != null) {
						startOffset = getStructuredDTDDocumentRegion().getEndOffset(region);
						replaceText(requestor, startOffset, 0, quoteChar + v + quoteChar);
					}
				}
			}
		}
	}

	/**
	 * Set the value of value.
	 * 
	 * @param v
	 *            Value to assign to value.
	 */
	public void setValue(String v) {
		beginRecording(this, DTDCorePlugin.getDTDString("_UI_LABEL_ENTITY_VALUE_CHG")); //$NON-NLS-1$
		setValue(this, v);
		endRecording(this);
	}

}
