package com.kurukurupapa.tryandroid.fw.util;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;

import com.kurukurupapa.tryandroid.fw.FwException;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Debug;
import android.provider.Settings.Secure;

public class FwUtil {

	/**
	 * デバッグモード判定
	 *
	 * マニフェストファイルのデバッグフラグから判定する。
	 *
	 * @param context
	 * @return デバッグモードの場合true
	 */
	public static boolean isDebuggable(Context context) {
		PackageManager manager = context.getPackageManager();
		ApplicationInfo appInfo = null;
		try {
			appInfo = manager.getApplicationInfo(context.getPackageName(), 0);
		} catch (NameNotFoundException e) {
			throw new FwException(e);
		}
		return (appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == ApplicationInfo.FLAG_DEBUGGABLE;
	}

	/**
	 * デバッグモード判定
	 *
	 * Android SDKのDebug#isDebuggerConnected()を使用。次の条件が成り立った場合にデバッグモードと判定する。<br />
	 * ・AndroidManifest.xmlのdebuggable="true"<br />
	 * ・PCとスマートフォンをUSB接続する<br />
	 * ・スマートフォン側のUSB接続時デバッグモードをtrueにする<br />
	 * ・DDMSにて、対象プロセスに対し「Debug process」を選択する
	 *
	 * @return
	 */
	public static boolean isDebuggerConnected() {
		return Debug.isDebuggerConnected();
	}

	/**
	 * エミュレーター判定
	 *
	 * エミュレーターの場合、個体識別番号が未設定であることから判定する。
	 *
	 * @param context
	 * @return エミュレーターの場合true
	 */
	public static boolean isEmulater(Context context) {
		String androidId = Secure.getString(context.getContentResolver(),
				Secure.ANDROID_ID);
		return androidId == null;
	}

	/**
	 * プロファイリング開始
	 *
	 * 出力されるファイルは、"/sdcard/com.tryandroid.fw.trace"です。
	 *
	 * 前提<br />
	 * ・AndroidManifest.xmlに「WRITE_EXTERNAL_STORAGE」権限を追加すること。
	 */
	public static void startMethodTracing() {
		Debug.startMethodTracing(FwUtil.class.getPackage().getName());
	}

	/**
	 * プロファイリング終了
	 */
	public static void stopMethodTracing() {
		Debug.stopMethodTracing();
	}

	public static int[] toPrimitiveArray(List<Integer> list) {
		int[] arr = new int[list.size()];
		for (int i = 0; i < list.size(); i++) {
			Integer value = list.get(i);
			if (value != null) {
				arr[i] = value;
			} else {
				arr[i] = 0;
			}
		}
		return arr;
	}

	public static String getFullStackTrace(Exception exception) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		exception.printStackTrace(pw);
		pw.flush();
		return sw.toString();
	}

	/**
	 * メソッド名を取得
	 *
	 * @return
	 */
	public static String getMethodName() {
		String name = "";
		StackTraceElement element = getStackTraceElement();
		if (element != null) {
			name = element.getMethodName();
		}
		return name;
	}

	/**
	 * StackTraceElementを取得
	 *
	 * @return
	 */
	public static StackTraceElement getStackTraceElement() {
		// スタックトレースを取得
		StackTraceElement[] elements = (new RuntimeException()).getStackTrace();

		// スタックトレースから、当クラス以外のトレースを見つける
		StackTraceElement element = null;
		for (int i = 1; i < elements.length; i++) {
			StackTraceElement e = elements[i];
			if (e.getClassName().indexOf(FwUtil.class.getName()) < 0) {
				element = e;
				break;
			}
		}

		return element;
	}

	/**
	 * Getter/Setter名から下記のルールに基づいてプロパティ名を取得します。<br>
	 * - 先頭"get","set","is"を取り除く。<br>
	 * - 先頭一文字を小文字にする。<br>
	 *
	 * @param getterSetterName
	 *            Getter/Setter名
	 * @return プロパティ名
	 */
	public static String getPropertyNameFromGetterSetterName(
			String getterSetterName) {
		String tmp = StringUtil.trimStart(getterSetterName, new String[] {
				"get", "set", "is" });
		if (tmp.length() > 0) {
			tmp = Character.toLowerCase(tmp.charAt(0)) + tmp.substring(1);
		}
		return tmp;
	}

	/**
	 * Getter/Setter名からプリファレンスのキー名を取得します。<br>
	 *
	 * @param getterSetterName
	 *            Getter/Setter名
	 * @return プリファレンスのキー名
	 */
	public static String getPreferenceKeyFromGetterSetterName(
			String getterSetterName) {
		return StringUtil
				.toUnderScore(getPropertyNameFromGetterSetterName(getterSetterName));
	}
}
