package com.kurukurupapa.tryandroid.fw.util;

import java.util.List;

import com.kurukurupapa.tryandroid.fw.FwException;

public class StringUtil {

	private enum CharType {
		Unknown, UpperCase, LowerCase, Digit, UnderScore
	}

	public static String toUnderScore(String camelCaseString) {
		CharType oldType = CharType.Unknown;
		CharType curType = CharType.Unknown;
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < camelCaseString.length(); i++) {
			char c = camelCaseString.charAt(i);
			boolean underScoreFlag = false;

			// 文字種類の判定と、'_'有無判定。
			if (Character.isUpperCase(c)) {
				curType = CharType.UpperCase;
				underScoreFlag = !curType.equals(oldType)
						&& !oldType.equals(CharType.UnderScore);
				c = Character.toLowerCase(c);

			} else if (Character.isLowerCase(c)) {
				curType = CharType.LowerCase;
				underScoreFlag = !curType.equals(oldType)
						&& !oldType.equals(CharType.UpperCase);

			} else if (Character.isDigit(c)) {
				curType = CharType.Digit;
				underScoreFlag = !curType.equals(oldType);

			} else if ('_' == c) {
				curType = CharType.UnderScore;
				underScoreFlag = false;

			} else {
				throw new FwException("変換失敗。camelCaseString=["
						+ camelCaseString + "]");
			}

			// 文字の種類が変わったとき、'_'を付加する。
			// ただし、先頭、または大文字から小文字の並び、では付けない。
			if (underScoreFlag && i > 0) {
				sb.append('_');
			}
			sb.append(c);

			// 次のループでも、現在の状態を覚えておく。
			oldType = curType;
		}

		// LogUtil.d(camelCaseString + "->" + sb.toString());
		return sb.toString();
	}

	public static String toCamelCaseString(String underScoreString) {
		boolean underScoreFlag = false;
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < underScoreString.length(); i++) {
			char c = underScoreString.charAt(i);

			if ('_' == c) {
				// アンダースコアは、出現を覚えておき、無視する。
				underScoreFlag = true;
			} else {
				// アンダースコア以外は、結果文字列に追加する。
				// このとき、前の文字ににアンダースコアがあれば、大文字化する。
				if (underScoreFlag) {
					c = Character.toUpperCase(c);
					underScoreFlag = false;
				}
				sb.append(c);
			}
		}

		return sb.toString();
	}

	public static boolean isNullOrEmpty(String str) {
		return (str == null || str.length() == 0);
	}

	public static String trimStart(String target, String trim) {
		return trimStart(target, new String[] { trim });
	}

	/**
	 * 対象文字列の先頭に、指定文字列が存在すれば、指定文字列を削除した文字列を返却する。 指定文字列が存在しなければ、変更なしで対象文字列を返却する。
	 *
	 * @param target
	 *            対象文字列
	 * @param trimArr
	 *            指定文字列の配列
	 * @return
	 */
	public static String trimStart(String target, String[] trimArr) {
		for (String trim : trimArr) {
			if (target.startsWith(trim)) {
				return target.substring(trim.length());
			}
		}
		return target;
	}

	/**
	 * 先頭を大文字に変換した文字列を取得する。
	 *
	 * @param 変換元文字列
	 * @return 変換後文字列
	 */
	public static String toUpperHead(String src) {
		return src.substring(0, 1).toUpperCase() + src.substring(1);
	}

	/**
	 * 配列要素を連結した文字列を取得する。
	 *
	 * @param list
	 *            文字列の配列。または文字列変換できる要素の配列。
	 * @param sep
	 *            区切り文字
	 * @return
	 */
	public static String join(List<? extends Object> list, String sep) {
		StringBuilder sb = new StringBuilder();
		for (Object obj : list) {
			if (sb.length() > 0) {
				sb.append(sep);
			}
			sb.append(obj);
		}
		return sb.toString();
	}
}
