/*******************************************************************************
 * Copyright (c) 2000, 2005 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.jdt.internal.core.dom.rewrite;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;

import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jface.text.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultLineTracker;
import org.eclipse.jface.text.ILineTracker;
import org.eclipse.jface.text.IRegion;

import org.eclipse.text.edits.ReplaceEdit;

/**
 * Helper class to provide String manipulation functions dealing with indents
 */
public class Indents {
	
	private Indents() {
		// don't instanciate
	}
	
	/**
	 * Tests if a character is an indent character. Indent character are all whitespace characters
	 * except the line delimiter characters.
	 * @param ch The character to test
	 * @return Returns <code>true</code> if this the character is a indent character
	 */
	public static boolean isIndentChar(char ch) {
		return Character.isWhitespace(ch) && !isLineDelimiterChar(ch);
	}

	/**
	 * Tests if a character is a line delimiter character.
	 * @param ch The character to test
	 * @return Returns <code>true</code> if this the character is a line delimiter character
	 */
	public static boolean isLineDelimiterChar(char ch) { 
		return ch == '\n' || ch == '\r';
	}	
	
	/**
	 * Returns the indentation of the given line in indentation units. Odd spaces are
	 * not counted. This method only analyzes the content of <code>line</code> up to the first
	 * non-whitespace character.
	 * 
	 * @param line the string to measure the indent of
	 * @param tabWidth the width of one tab character in space equivalents
	 * @param indentWidth the width of one indentation unit in space equivalents
	 * @return the number of indentation units that line is indented by
	 */
	public static int measureIndentUnits(CharSequence line, int tabWidth, int indentWidth) {
		if (indentWidth <= 0 || tabWidth < 0 || line == null) {
			throw new IllegalArgumentException();
		}
		
		int visualLength= measureIndentInSpaces(line, tabWidth);
		return visualLength / indentWidth;
	}
	
	/**
	 * Returns the indentation of the given line in space equivalents.
	 * Tab characters are counted using the given <code>tabWidth</code> and every other indent
	 * character as one. This method analyzes the content of <code>line</code> up to the first
	 * non-whitespace character.
	 * 
	 * @param line the string to measure the indent of
	 * @param tabWidth the width of one tab in space equivalents
	 * @return the measured indent width in space equivalents
	 */
	public static int measureIndentInSpaces(CharSequence line, int tabWidth) {
		if (tabWidth < 0 || line == null) {
			throw new IllegalArgumentException();
		}
		
		int length= 0;
		int max= line.length();
		for (int i= 0; i < max; i++) {
			char ch= line.charAt(i);
			if (ch == '\t') {
				int reminder= length % tabWidth;
				length += tabWidth - reminder;
			} else if (isIndentChar(ch)) {
				length++;
			} else {
				return length;
			}
		}
		return length;
	}
	
	/**
	 * Returns the leading indentation string of the given line. Note that the returned string
	 * need not be equal to the leading whitespace as odd spaces are not considered part of the
	 * indentation.
	 * 
	 * @param line the line to scan
	 * @param tabWidth the size of one tab in space equivalents
	 * @param indentWidth the width of one indentation unit in space equivalents
	 * @return the indent part of <code>line</code>, but no odd spaces
	 */
	public static String extractIndentString(String line, int tabWidth, int indentWidth) {
		if (tabWidth < 0 || indentWidth <= 0 || line == null) {
			throw new IllegalArgumentException();
		}
		
		int size= line.length();
		int end= 0;
		
		int spaceEquivs= 0;
		int characters= 0;
		for (int i= 0; i < size; i++) {
			char c= line.charAt(i);
			if (c == '\t') {
				int remainder= spaceEquivs % tabWidth;
				spaceEquivs += tabWidth - remainder;
				characters++;
			} else if (isIndentChar(c)) {
				spaceEquivs++;
				characters++;
			} else {
				break;
			}
			if (spaceEquivs >= indentWidth) {
				end += characters;
				characters= 0;
				spaceEquivs= spaceEquivs % indentWidth;
			}
		}
		if (end == 0)
			return ""; //$NON-NLS-1$
		else if (end == size)
			return line;
		else
			return line.substring(0, end);
	}

	
	/**
	 * Removes the given number of indentation units from a given line. If the line 
	 * does not have the given indent, all the available indentation is removed.
	 * If <code>indentsToRemove <= 0</code> the line is returned.
	 *
	 * 	@param line the line to trim
	 * @param tabWidth the width of one tab in space equivalents
	 * @param indentWidth the width of one indentation unit in space equivalents
	 * @return the trimmed string
	 */
	public static String trimIndent(String line, int indentUnitsToRemove, int tabWidth, int indentWidth) {
		if (tabWidth < 0 || indentWidth <= 0 || line == null) {
			throw new IllegalArgumentException();
		}
		
		if (indentUnitsToRemove <= 0)
			return line;

		final int spaceEquivalentsToRemove= indentUnitsToRemove * indentWidth;
		
		int start= 0;
		int spaceEquivalents= 0;
		int size= line.length();
		String prefix= null;
		for (int i= 0; i < size; i++) {
			char c= line.charAt(i);
			if (c == '\t') {
				int remainder= spaceEquivalents % tabWidth;
				spaceEquivalents += tabWidth - remainder;
			} else if (isIndentChar(c)) {
				spaceEquivalents++;
			} else {
				// Assert.isTrue(false, "Line does not have requested number of indents");
				start= i;
				break; 
			}
			if (spaceEquivalents == spaceEquivalentsToRemove) {
				start= i + 1;
				break;
			}
			if (spaceEquivalents > spaceEquivalentsToRemove) {
				// can happen if tabSize > indentSize, e.g tabsize==8, indent==4, indentsToRemove==1, line prefixed with one tab
				// this implements the third option
				start= i + 1; // remove the tab
				// and add the missing spaces
				char[] missing= new char[spaceEquivalents - spaceEquivalentsToRemove];
				Arrays.fill(missing, ' ');
				prefix= new String(missing);
				break;
			}
		}
		String trimmed;
		if (start == size)
			trimmed= ""; //$NON-NLS-1$
		else
			trimmed= line.substring(start);
		
		if (prefix == null)
			return trimmed;
		return prefix + trimmed;
	}

	/**
	 * Change the indent of a, possible muti-line, code string. The given number of indent units is removed,
	 * and a new indent string is added.
	 * The first line of the code will not be changed (It is considered to have no indent as it might start in
	 * the middle of a line).
	 * 
	 * 	@param code the code to change the indent of
	 * 	@param indentUnitsToRemove the number of indent units to remove from each line (except the first) of the given code
	 * @param tabWidth the size of one tab in space equivalents
	 * @param indentWidth the width of one indentation unit in space equivalents
	 * 	@param newIndentString the new indent string to be added to all lines (except the first)
	 * 	@param lineDelim the new line delimiter to be used. The returned code will contain only this line delimiter.
	 * @return the newly indent code, containing only the given line delimiters.
	 */
	public static String changeIndent(String code, int indentUnitsToRemove, int tabWidth, int indentWidth, String newIndentString, String lineDelim) {
		if (tabWidth < 0 || indentWidth <= 0 || code == null || indentUnitsToRemove < 0 || newIndentString == null || lineDelim == null) {
			throw new IllegalArgumentException();
		}
		
		try {
			ILineTracker tracker= new DefaultLineTracker();
			tracker.set(code);
			int nLines= tracker.getNumberOfLines();
			if (nLines == 1) {
				return code;
			}
			
			StringBuffer buf= new StringBuffer();
			
			for (int i= 0; i < nLines; i++) {
				IRegion region= tracker.getLineInformation(i);
				int start= region.getOffset();
				int end= start + region.getLength();
				String line= code.substring(start, end);
				
				if (i == 0) {  // no indent for first line (contained in the formatted string)
					buf.append(line);
				} else { // no new line after last line
					buf.append(lineDelim);
					buf.append(newIndentString); 
					buf.append(trimIndent(line, indentUnitsToRemove, tabWidth, indentWidth));
				}
			}
			return buf.toString();
		} catch (BadLocationException e) {
			// can not happen
			return code;
		}
	}

	/**
	 * Change the indent of a, possible muti-line, code string. The given number of indent units is removed,
	 * and a new indent string is added.
	 * The first line of the code will not be changed (It is considered to have no indent as it might start in
	 * the middle of a line).
	 * @param source The code to change the indent of
	 * 	@param indentUnitsToRemove the number of indent units to remove from each line (except the first) of the given code
	 * @param tabWidth the size of one tab in space equivalents
	 * @param indentWidth the width of one indentation unit in space equivalents
	 * 	@param newIndentString the new indent string to be added to all lines (except the first)
	 * @return returns the resulting text edits
	 */
	public static ReplaceEdit[] getChangeIndentEdits(String source, int indentUnitsToRemove, int tabWidth, int indentWidth, String newIndentString) {
		if (tabWidth < 0 || indentWidth <= 0 || source == null || indentUnitsToRemove < 0 || newIndentString == null) {
			throw new IllegalArgumentException();
		}
		
		ArrayList result= new ArrayList();
		try {
			ILineTracker tracker= new DefaultLineTracker();
			tracker.set(source);
			int nLines= tracker.getNumberOfLines();
			if (nLines == 1)
				return (ReplaceEdit[])result.toArray(new ReplaceEdit[result.size()]);
			for (int i= 1; i < nLines; i++) {
				IRegion region= tracker.getLineInformation(i);
				int offset= region.getOffset();
				String line= source.substring(offset, offset + region.getLength());
				int length= indexOfIndent(line, indentUnitsToRemove, tabWidth, indentWidth);
				if (length >= 0) {
					result.add(new ReplaceEdit(offset, length, newIndentString));
				} else {
					length= measureIndentUnits(line, tabWidth, indentWidth);
					result.add(new ReplaceEdit(offset, length, "")); //$NON-NLS-1$
				}
			}
		} catch (BadLocationException cannotHappen) {
			// can not happen
		}
		return (ReplaceEdit[])result.toArray(new ReplaceEdit[result.size()]);
	}
	
	/*
	 * Returns the index where the indent of the given size ends.
	 * Returns <code>-1<code> if the line isn't prefixed with an indent of
	 * the given number of indents.
	 */
	private static int indexOfIndent(CharSequence line, int numberOfIndentUnits, int tabWidth, int indentWidth) {
		
		int spaceEquivalents= numberOfIndentUnits * indentWidth;
		
		int size= line.length();
		int result= -1;
		int blanks= 0;
		for (int i= 0; i < size && blanks < spaceEquivalents; i++) {
			char c= line.charAt(i);
			if (c == '\t') {
				int remainder= blanks % tabWidth;
				blanks += tabWidth - remainder;
			} else if (isIndentChar(c)) {
				blanks++;
			} else {
				break;
			}
			result= i;
		}
		if (blanks < spaceEquivalents)
			return -1;
		return result + 1;
	}
	
	/**
	 * Returns the tab width as configured in the given map.
	 * @param options the map to get the formatter settings from. Use {@link org.eclipse.jdt.core.IJavaProject#getOptions(boolean)} to
	 * get the most current project options.
	 * @return the tab width
	 */
	public static int getTabWidth(Map options) {
		if (options == null) {
			throw new IllegalArgumentException();
		}
		return getIntValue(options, DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, 4);
	}
	
	/**
	 * Returns the tab width as configured in the given map.
	 * @param options the map to get the formatter settings from. Use {@link org.eclipse.jdt.core.IJavaProject#getOptions(boolean)} to
	 * get the most current project options.
	 * @return the indent width
	 */
	public static int getIndentWidth(Map options) {
		if (options == null) {
			throw new IllegalArgumentException();
		}
		int tabWidth=getTabWidth(options);
		boolean isMixedMode= DefaultCodeFormatterConstants.MIXED.equals(options.get(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR));
		if (isMixedMode) {
			return getIntValue(options, DefaultCodeFormatterConstants.FORMATTER_INDENTATION_SIZE, tabWidth);
		}
		return tabWidth;
	}
	
	/**
	 * Creates a string that represents the given number of indentation units.
	 * The returned string can contain tabs and/or spaces depending on the core
	 * formatter preferences.
	 * 
	 * @param indentationUnits the number of indentation units to generate
	 * @param options the options to get the formatter settings from. Use {@link org.eclipse.jdt.core.IJavaProject#getOptions(boolean)} to
	 * get the most current project options.
	 * @return the indent string
	 */
	public static String createIndentString(int indentationUnits, Map options) {
		if (options == null || indentationUnits < 0) {
			throw new IllegalArgumentException();
		}
		
		String tabChar= getStringValue(options, DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.TAB);
		
		final int tabs, spaces;
		if (JavaCore.SPACE.equals(tabChar)) {
			tabs= 0;
			spaces= indentationUnits * getIndentWidth(options);
		} else if (JavaCore.TAB.equals(tabChar)) {
			// indentWidth == tabWidth
			tabs= indentationUnits;
			spaces= 0;
		} else if (DefaultCodeFormatterConstants.MIXED.equals(tabChar)){
			int tabWidth= getTabWidth(options);
			int spaceEquivalents= indentationUnits * getIndentWidth(options);
			if (tabWidth > 0) {
				tabs= spaceEquivalents / tabWidth;
				spaces= spaceEquivalents % tabWidth;
			} else {
				tabs= 0;
				spaces= spaceEquivalents;
			}
		} else {
			// new indent type not yet handled
			Assert.isTrue(false);
			return null;
		}
		
		StringBuffer buffer= new StringBuffer(tabs + spaces);
		for(int i= 0; i < tabs; i++)
			buffer.append('\t');
		for(int i= 0; i < spaces; i++)
			buffer.append(' ');
		return buffer.toString();
	}
	
	private static String getStringValue(Map options, String key, String def) {
		Object value= options.get(key);
		if (value instanceof String)
			return (String) value;
		return def;
	}
	
	private static int getIntValue(Map options, String key, int def) {
		try {
			return Integer.parseInt((String) options.get(key));
		} catch (NumberFormatException e) {
			return def;
		}
	}
}

