/*******************************************************************************
 * Copyright (c) 2010, 2011 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 ******************************************************************************/
package org.eclipse.equinox.bidi.advanced;

import org.eclipse.equinox.bidi.custom.StructuredTextTypeHandler;

/**
 * Provides advanced methods for processing bidirectional text with 
 * a specific structure to ensure proper presentation.
 * For a general introduction to structured text, see the 
 * {@link org.eclipse.equinox.bidi
 * package documentation}.
 * For details about when the advanced methods are needed, see
 * {@link org.eclipse.equinox.bidi.advanced this
 * package documentation}.
 * <p>
 * Identifiers for several common handlers are included in 
 * {@link org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory}. For handlers 
 * supplied by other packages, a handler instance can be obtained using the
 * {@link org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory#getHandler}
 * method for the registered handlers, or by instantiating a private handler.
 * </p><p>
 * Most of the methods in this interface have a <code>text</code>
 * argument which may be just a part of a larger body of text.
 * When it is the case that the text is submitted in parts with
 * repeated calls, there may be a need to pass information from
 * one invocation to the next one. For instance, one invocation
 * may detect that a comment or a literal has been started but
 * has not been completed. In such cases, the state must be managed
 * by a {@link IStructuredTextExpert} instance obtained with the 
 * {@link StructuredTextExpertFactory#getStatefulExpert} method.
 * </p><p>
 * The <code>state</code> returned after processing a string
 * can be retrieved, set and reset using the {@link #getState()},
 * {@link #setState(Object)} and {@link #clearState()} methods.
 * </p><p>
 * When submitting the initial part of a text, the state should be
 * reset if it is not the first processing call for this 
 * {@link IStructuredTextExpert} instance.
 * </p><p>
 * Values returned by {@link #getState()} are opaque objects whose meaning
 * is internal to the relevant structured type handler. These values can only
 * be used in {@link #setState(Object)} calls to restore a state
 * previously obtained after processing a given part of a text before 
 * processing the next part of the text.
 * </p><p>
 * Note that if the user does not modify the state, the state returned by
 * a given processing call is automatically passed as initial state to the
 * next processing call, provided that the expert is a stateful one.
 * </p><p>
 * <b>Code Samples</b>
 * </p><p>
 * The following code shows how to transform a certain type of structured text
 * (directory and file paths) in order to obtain the <i>full</i>
 * text corresponding to the given <i>lean</i> text.</p>
 * <pre>
 *   IStructuredTextExpert expert = StructuredTextExpertFactory.getExpert(StructuredTextTypeHandlerFactory.FILE);
 *   String leanText = "D:\\\u05d0\u05d1\\\u05d2\\\u05d3.ext";
 *   String fullText = expert.leanToFullText(leanText);
 *   System.out.println("full text = " + fullText);
 * </pre>
 * <p>
 * The following code shows how to transform successive lines of Java
 * code in order to obtain the <i>full</i>
 * text corresponding to the <i>lean</i> text of each line.</p>
 * <pre>
 *   IStructuredTextExpert expert = StructuredTextExpertFactory.getStatefulExpert(StructuredTextTypeHandlerFactory.JAVA);
 *   String leanText = "int i = 3; // first Java statement";
 *   String fullText = expert.leanToFullText(leanText);
 *   System.out.println("full text = " + fullText);
 *   leanText = "i += 4; // next Java statement";
 *   fullText = expert.leanToFullText(leanText,);
 *   System.out.println("full text = " + fullText);
 * </pre>
 * 
 */
public interface IStructuredTextExpert {

	/**
	 *  Constant specifying that the base direction of a structured text is LTR.
	 *  The base direction may depend on whether the GUI is
	 *  {@link StructuredTextEnvironment#getMirrored mirrored} and
	 *  may be different for Arabic and for Hebrew.
	 *  This constant can appear as value returned by the
	 *  {@link #getTextDirection} method.
	 */
	public static final int DIR_LTR = 0;

	/**
	 *  Constant specifying that the base direction of a structured text is RTL.
	 *  The base direction may depend on whether the GUI is
	 *  {@link StructuredTextEnvironment#getMirrored mirrored} and may
	 *  may be different for Arabic and for Hebrew.
	 *  This constant can appear as value returned by the
	 *  {@link #getTextDirection} method.
	 */
	public static final int DIR_RTL = 1;

	/**
	 * Obtains the structured type handler associated with this 
	 * <code>IStructuredTextExpert</code> instance.
	 * 
	 * @return the type handler instance.
	 */
	public StructuredTextTypeHandler getTypeHandler();

	/**
	 * Obtains the environment associated with this 
	 * <code>IStructuredTextExpert</code> instance.
	 * @return the environment instance.
	 */
	public StructuredTextEnvironment getEnvironment();

	/** 
	 * Adds directional formatting characters to a structured text
	 * to ensure correct presentation.
	 * 
	 * @param text is the structured text string
	 *
	 * @return the structured text with directional formatting characters added to ensure 
	 * correct presentation.
	 */
	public String leanToFullText(String text);

	/**
	 * Given a <i>lean</i> string, computes the positions of each of its
	 * characters within the corresponding <i>full</i> string.
	 *
	 * @param text is the structured text string.
	 *
	 * @return an array of integers with one element for each of the
	 * characters in the <code>text</code> argument, equal to the offset
	 * of the corresponding character in the <i>full</i> string.
	 */
	public int[] leanToFullMap(String text);

	/**
	 * Given a <i>lean</i> string, computes the offsets of characters
	 * before which directional formatting characters must be added
	 * in order to ensure correct presentation.
	 * <p>
	 * Only LRMs (for a string with LTR base direction) and RLMs (for
	 * a string with RTL base direction) are considered. Leading and
	 * trailing LRE, RLE and PDF which might be prefixed or suffixed
	 * depending on the {@link StructuredTextEnvironment#getOrientation orientation} of the
	 * GUI component used for display are not reflected in this method.
	 * </p>
	 * @param text is the structured text string
	 *
	 * @return an array of offsets to the characters in the <code>text</code> argument 
	 * before which directional marks must be added to ensure correct presentation.
	 * The offsets are sorted in ascending order.
	 */
	public int[] leanBidiCharOffsets(String text);

	/**
	 * Removes directional formatting characters which were added to a
	 * structured text string to ensure correct presentation.
	 *
	 * @param text is the structured text string including directional formatting characters.
	 *
	 * @return the structured text string without directional formatting characters 
	 * which might have been added by processing it with {@link #leanToFullText}.
	 *
	 */
	public String fullToLeanText(String text);

	/**
	 * Given a <i>full</i> string, computes the positions of each of its
	 * characters within the corresponding <i>lean</i> string.
	 *
	 * @param  text is the structured text string including directional formatting characters.
	 *
	 * @return an array of integers with one element for each of the
	 * characters in the <code>text</code> argument, equal to the offset
	 * of the corresponding character in the <i>lean</i> string.
	 * If there is no corresponding character in the <i>lean</i> string 
	 * (because the specified character is a directional formatting character
	 * added when invoking {@link #leanToFullText}), 
	 * the value returned for this character is -1.
	 */
	public int[] fullToLeanMap(String text);

	/**
	 * Given a <i>full</i> string, returns the offsets of characters
	 * which are directional formatting characters that have been added
	 * in order to ensure correct presentation.
	 * <p>
	 * LRMs (for a string with LTR base direction), RLMs (for a string with RTL base direction) 
	 * are considered as well as leading and trailing LRE, RLE and PDF which might be prefixed 
	 * or suffixed depending on the {@link StructuredTextEnvironment#getOrientation orientation} 
	 * of the GUI component used for display.
	 * </p>
	 * @param  text is the structured text string including directional formatting characters
	 *
	 * @return an array of offsets to the characters in the <code>text</code> argument which 
	 * are directional formatting characters added to ensure correct presentation. The offsets 
	 * are sorted in ascending order.
	 */
	public int[] fullBidiCharOffsets(String text);

	/** 
	 * Adds directional marks to the given text before the characters 
	 * specified in the given array of offsets. It can be used to add a prefix and/or 
	 * a suffix of directional formatting characters.
	 * <p>
	 * The directional marks will be LRMs for structured text strings with LTR base 
	 * direction and RLMs for strings with RTL base direction.
	 * </p><p> 
	 * If necessary, leading and trailing directional formatting characters
	 * (LRE, RLE and PDF) can be added depending on the value of the 
	 * <code>affix</code> argument.</p>
	 * <ul>
	 *   <li>A value of 1 means that one LRM or RLM must be prefixed, depending  
	 *       on the direction. This is useful when the GUI component presenting
	 *       this text has a contextual orientation.</li>
	 *   <li>A value of 2 means that LRE+LRM or RLE+RLM must be prefixed, 
	 *       depending on the direction, and LRM+PDF or RLM+PDF must be
	 *       suffixed, depending on the direction.
	 *       This is useful if the GUI component presenting this text needs to
	 *       have the text orientation explicitly specified.</li>
	 *   <li>A value of 0 means that no prefix or suffix are needed.</li>
	 * </ul>
	 * @see IStructuredTextExpert#leanBidiCharOffsets(String)
	 * 
	 * @param  text the structured text string
	 * @param  offsets an array of offsets to characters in <code>text</code>
	 *         before which an LRM or RLM will be inserted.
	 *         The array must be sorted in ascending order without duplicates.
	 *         This argument may be <code>null</code> if there are no marks to add.
	 * @param  direction the base direction of the structured text.
	 *         It must be one of the values {@link #DIR_LTR}, or
	 *         {@link #DIR_RTL}.
	 * @param  affixLength specifies the length of prefix and suffix 
	 *         which should be added to the result.<br>
	 *         0 means no prefix or suffix<br>
	 *         1 means one LRM or RLM as prefix and no suffix<br>
	 *         2 means 2 characters in both prefix and suffix.
	 *         
	 * @return a string corresponding to the source <code>text</code> with
	 *         directional marks (LRMs or RLMs) added at the specified offsets,
	 *         and directional formatting characters (LRE, RLE, PDF) added
	 *         as prefix and suffix if so required.
	 */
	public String insertMarks(String text, int[] offsets, int direction, int affixLength);

	/**
	 * Get the base direction of a structured text. This base direction may depend on
	 * whether the text contains Arabic or Hebrew words. If the text contains both, 
	 * the first Arabic or Hebrew letter in the text determines which is the governing script.
	 *
	 * @param  text is the structured text string.
	 *
	 * @return the base direction of the structured text, {@link #DIR_LTR} or {@link #DIR_RTL}
	 */
	public int getTextDirection(String text);

	//////////////////////////////////////////////////////////////////////
	// Expert's state handling - can be used only for non-shared experts
	//////////////////////////////////////////////////////////////////////
	/**
	 * Sets the state for the next text processing call.
	 * This method does nothing if the expert instance is not a stateful one.
	 * 
	 * @param state an object returned by a previous call to {@link #getState}.
	 */
	public void setState(Object state);

	/**
	 * Gets the state established by the last text processing call.
	 * This is <code>null</code> if the expert instance is not a stateful one,
	 * or if the last text processing call had nothing to pass to the next call.
	 * 
	 * @return the last established state.
	 */
	public Object getState();

	/**
	 * Resets the state to initial.
	 * This method does nothing if the expert instance is not a stateful one.
	 */
	public void clearState();
}
