package com.one;

import com.vmx.AuxClass;
import com.vmx.Locale;
import com.vmx.StringEncoder;
import java.util.Enumeration;
import java.util.Vector;

/**
 * Класс для обработки текста
 */
public class TextProcessor
{
	/**
	 * Замена в строке хитрых символов экранированными.
	 *
	 * Символы вроде CR, LF и TAB заменяются буквенными сочетаниями,
	 * все остальные символы до пробела - октальными.
	 * Также заменяются октальными или юникодовыми сочетаниями
	 * все символы, которые не входят в указанную кодировку.
	 */
	public static String escapeString(String text, int enc)
	{
		StringBuffer res = new StringBuffer(text.length());
		char[] src = text.toCharArray();
		int index;
		char c;

		if(enc >= 0)
		{
			for(int i = 0; i < src.length; i++)
			{
				c = src[i];
				index = "\b\f\n\r\t\\".indexOf(c);

				if(index >= 0)
				{
					res.append('\\');
					res.append("bfnrt\\".charAt(index));
				}
				else if(c < 8)
				{
					res.append('\\');
					res.append('0');
					res.append('0');
					res.append(Integer.toOctalString(c));
				}
				else if(c < 32)
				{
					res.append('\\');
					res.append('0');
					res.append(Integer.toOctalString(c));
				}
				else if(c >= 128 && StringEncoder.decodeChar(StringEncoder.encodeChar(c, enc), enc) != c)
				{
					if(c < 256)
					{
						res.append('\\');
						res.append(Integer.toOctalString(c));
					}
					else if(c < 4096)
					{
						res.append('\\');
						res.append('u');
						res.append('0');
						res.append(Integer.toHexString(c).toUpperCase());
					}
					else
					{
						res.append('\\');
						res.append('u');
						res.append(Integer.toHexString(c).toUpperCase());
					}
				}
				else
				{
					res.append(c);
				}
			}
		}
		else
		{
			for(int i = 0; i < src.length; i++)
			{
				c = src[i];
				index = "\b\f\n\r\t\\".indexOf(c);

				if(index >= 0)
				{
					res.append('\\');
					res.append("bfnrt\\".charAt(index));
				}
				else if(c < 8)
				{
					res.append('\\');
					res.append('0');
					res.append('0');
					res.append(Integer.toOctalString(c));
				}
				else if(c < 32)
				{
					res.append('\\');
					res.append('0');
					res.append(Integer.toOctalString(c));
				}
				else
				{
					res.append(c);
				}
			}
		}

		return res.toString();
	}

	/**
	 * Замена в строке экранированных символов их значениями.
	 *
	 * Распознаются как буквенные сочетания вроде CR, LF и TAB,
	 * так и октальные и юникодовые.
	 */
	public static String unescapeString(String text)
	{
		StringBuffer res = new StringBuffer(text.length());
		int index, subindex, rc;
		char c;

		while(text.length() > 0)
		{
			index = text.indexOf('\\');

			if(index >= 0)
			{
				res.append(text.substring(0, index));

				c = Character.toLowerCase(text.charAt(++index));
				subindex = "bfnrt\\".indexOf(c);

				if(subindex >= 0)
				{
					res.append("\b\f\n\r\t\\".charAt(subindex));
					text = text.substring(index + 1);
				}
				else if(c == 'u')
				{
					index++;
					rc = 0;

					for(int i = 0; i < 4 && index < text.length(); i++)
					{
						subindex = "0123456789ABCDEF".indexOf(Character.toUpperCase(text.charAt(index++)));

						if(subindex >= 0)
						{
							rc = (rc << 4) | subindex;
						}
						else
						{
							break;
						}
					}

					res.append((char)rc);
					text = text.substring(index);
				}
				else
				{
					rc = 0;

					for(int i = 0; i < 3 && index < text.length(); i++)
					{
						subindex = "01234567".indexOf(text.charAt(index++));

						if(subindex >= 0)
						{
							rc = (rc << 3) | subindex;
						}
						else
						{
							break;
						}
					}

					res.append((char)rc);
					text = text.substring(index);
				}
			}
			else
			{
				res.append(text);
				break;
			}
		}

		return res.toString();
	}

	/**
	 * Создать массив пробелов для функии tabsToSpaces.
	 *
	 * @param tabsize число пробелов на один знак табуляции
	 * @return массив строк с пробелами (" ", "  ", "   ", ...)
	 */
	public static String[] createSpaces(int tabsize)
	{
		String[] spaces = new String[tabsize];
		spaces[0] = " ";

		for(int i = 1; i < tabsize; i++)
		{
			spaces[i] = spaces[i - 1] + ' ';
		}
		return spaces;
	}

	/**
	 * Заменить в строке табуляцию пробелами.
	 *
	 * В точном режиме количество вставляемых пробелов зависит от конфигурации строки,
	 * то есть в случае моноширинного шрифта будет реальная табуляция по колонкам.
	 *
	 * В простом режиме каждый символ табуляции заменяется фиксированным числом пробелов,
	 * что больше подходит для пропорциональных шрифтов.
	 *
	 * @param text строка
	 * @param spaces массив строк с пробелами (" ", "  ", "   ", ...)
	 * @param accurate true - точная замена, false - простая замена
	 * @return строка
	 */
	public static String tabsToSpaces(String text, String[] spaces, boolean accurate)
	{
		int tabsize = spaces.length;
		int index = 0;

		if(accurate)
		{
			while((index = text.indexOf('\t')) >= 0)
			{
				text = text.substring(0, index) + spaces[tabsize - (index % tabsize) - 1] + text.substring(index + 1);
			}
		}
		else
		{
			while((index = text.indexOf('\t')) >= 0)
			{
				text = text.substring(0, index) + spaces[tabsize - 1] + text.substring(index + 1);
			}
		}

		return text;
	}

	/**
	 * Чередует символы из первой строки с другой строкой.
	 */
	public static String interlaceString(String text, String filler)
	{
		StringBuffer res = new StringBuffer(text.length() + filler.length() * (text.length() - 1));
		char[] cs = text.toCharArray();

		res.append(cs[0]);

		for(int i = 1; i < cs.length; i++)
		{
			res.append(filler);
			res.append(cs[i]);
		}

		return res.toString();
	}

	/**
	 * Преобразовать массив байт в строку символов,
	 * соответствующих этим байтам.
	 */
	public static String byteArrayToString(byte[] b)
	{
		char[] cs = new char[b.length];

		for(int i = 0; i < b.length; i++)
		{
			cs[i] = (char)((int)b[i] & 0xFF);
		}

		return new String(cs);
	}

	/**
	 * Убрать из строки все упавляющие символы.
	 */
	public static String removeControlChars(String text)
	{
		StringBuffer res = new StringBuffer(text.length());

		char[] cs = text.toCharArray();

		for(int i = 0; i < cs.length; i++)
		{
			if(cs[i] >= ' ')
			{
				res.append(cs[i]);
			}
		}

		return res.toString();
	}

	/**
	 * Преобразовать вектор в массив строчек.
	 *
	 * @param vector вектор со строчками
	 * @return массив строчек
	 */
	public static String[] vectorToStringArray(Vector vector)
	{
		String[] res = new String[vector.size()];
		vector.copyInto(res);

		return res;
	}

	/**
	 * Преобразовать перечисление в массив срочек.
	 *
	 * @param enumeration перечислени строчек
	 * @return массив строчек
	 */
	public static String[] enumerationToStringArray(Enumeration enumeration)
	{
		Vector vector = new Vector();

		while(enumeration.hasMoreElements())
		{
			vector.addElement(enumeration.nextElement());
		}

		String[] res = new String[vector.size()];
		vector.copyInto(res);

		return res;
	}

	/**
	 * Замемена текста в строке.
	 *
	 * @param text исходная строка
	 * @param replaceWhat что заменять
	 * @param replaceWith чем заменять
	 * @return обновленная строка
	 */
	public static String replaceText(String text, String replaceWhat, String replaceWith)
	{
		if(replaceWhat.equals(replaceWith))
		{
			return text;
		}

		int replen = replaceWhat.length();
		int index;

		while(true)
		{
			index = text.indexOf(replaceWhat);

			if(index >= 0)
			{
				text = text.substring(0, index) + replaceWith + text.substring(index + replen);
			}
			else
			{
				break;
			}
		}

		return text;
	}

	public static String getString(Object object, String text)
	{
		if(text.startsWith("#"))
		{
			try
			{
				return Locale.getString(object, Integer.parseInt(text.substring(1).trim()));
			}
			catch(NumberFormatException nfe)
			{
				return text;
			}
		}
		else
		{
			return text;
		}
	}
}
