package com.android.metro.bridge;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.text.NumberFormat;

import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;

public class uDebug
{
	private static boolean cmd_on = false;
	private static boolean default_time_on = false;
	private uLock lock = new uLock();
	private String sHead = "\u001B[32m\u001B[1m[KMH]\u001B[0m";
	private KeyString key=null;
	private long ltime_one = 0;

	public static boolean is_sdcard_mount = false;
//	public static boolean save_log_off = true;	// 로그캣 제외

	private static boolean is_signal_log = false;
	private static long LOG_SIZE = 10*1024*1024;
	private static int LOG_MAX_COUNT = 7;	// 15메가까지 증가한 것도 본적이 있음,
											// 7개면 약 105메가이므로 10개에서 줄임

//	private static Boolean save_logcat = false;
/**
	private static Boolean dont_save_logcat = false;
	private static Runnable mCheckSaveLogcatRunnable = new Runnable() {
		@Override
		public void run() {
			while (null != mCheckSaveLogcat && mCheckSaveLogcat.isAlive() && !mCheckSaveLogcat.isInterrupted()) {
				Utils.Sleep(5000);

//				synchronized (save_logcat) {
//					if (!save_logcat) {
//						if (Utils.FileExist("/sdcard/metro/log/save_logcat")) {
//							save_logcat = true;
//							ToFile();
//						}
//					} else {
//						if (!Utils.FileExist("/sdcard/metro/log/save_logcat")) {
//							save_logcat = false;
//							KillLogcat();
//						}
//					}
//				}
				synchronized (dont_save_logcat) {
					if (!dont_save_logcat) {
						if (Utils.FileExist("/sdcard/metro/log/dont_save_logcat")) {
							dont_save_logcat = true;
							KillLogcat();
						}
					} else {
						if (!Utils.FileExist("/sdcard/metro/log/dont_save_logcat")) {
							dont_save_logcat = false;
							ToFile();
						}
					}
				}
			}
		}
	};
	private static Thread mCheckSaveLogcat = new Thread(mCheckSaveLogcatRunnable, "mCheckSaveLogcat");
*/

	private class KeyString{
		private class KeyTable{
			int code;
			String name;
			public KeyTable(int ic, String sn) {
				code = ic;
				name = sn;
			}
		}
		private KeyTable[] mKeyTable = new KeyTable[]{
				new KeyTable(KeyEvent.KEYCODE_UNKNOWN,"UNKNOWN"),
				new KeyTable(KeyEvent.KEYCODE_SOFT_LEFT,"SOFT_LEFT"),
				new KeyTable(KeyEvent.KEYCODE_SOFT_RIGHT,"SOFT_RIGHT"),
				new KeyTable(KeyEvent.KEYCODE_HOME,"HOME"),
				new KeyTable(KeyEvent.KEYCODE_BACK,"BACK"),
				new KeyTable(KeyEvent.KEYCODE_CALL,"CALL"),
				new KeyTable(KeyEvent.KEYCODE_ENDCALL,"ENDCALL"),
				new KeyTable(KeyEvent.KEYCODE_0,"0"),
				new KeyTable(KeyEvent.KEYCODE_1,"1"),
				new KeyTable(KeyEvent.KEYCODE_2,"2"),
				new KeyTable(KeyEvent.KEYCODE_3,"3"),
				new KeyTable(KeyEvent.KEYCODE_4,"4"),
				new KeyTable(KeyEvent.KEYCODE_5,"5"),
				new KeyTable(KeyEvent.KEYCODE_6,"6"),
				new KeyTable(KeyEvent.KEYCODE_7,"7"),
				new KeyTable(KeyEvent.KEYCODE_8,"8"),
				new KeyTable(KeyEvent.KEYCODE_9,"9"),
				new KeyTable(KeyEvent.KEYCODE_STAR,"STAR"),
				new KeyTable(KeyEvent.KEYCODE_POUND,"POUND"),
				new KeyTable(KeyEvent.KEYCODE_DPAD_UP,"DPAD_UP"),
				new KeyTable(KeyEvent.KEYCODE_DPAD_DOWN,"DPAD_DOWN"),
				new KeyTable(KeyEvent.KEYCODE_DPAD_LEFT,"DPAD_LEFT"),
				new KeyTable(KeyEvent.KEYCODE_DPAD_RIGHT,"DPAD_RIGHT"),
				new KeyTable(KeyEvent.KEYCODE_DPAD_CENTER,"DPAD_CENTER"),
				new KeyTable(KeyEvent.KEYCODE_VOLUME_UP,"VOLUME_UP"),
				new KeyTable(KeyEvent.KEYCODE_VOLUME_DOWN,"VOLUME_DOWN"),
				new KeyTable(KeyEvent.KEYCODE_POWER,"POWER"),
				new KeyTable(KeyEvent.KEYCODE_CAMERA,"CAMERA"),
				new KeyTable(KeyEvent.KEYCODE_CLEAR,"CLEAR"),
				new KeyTable(KeyEvent.KEYCODE_A,"A"),
				new KeyTable(KeyEvent.KEYCODE_B,"B"),
				new KeyTable(KeyEvent.KEYCODE_C,"C"),
				new KeyTable(KeyEvent.KEYCODE_D,"D"),
				new KeyTable(KeyEvent.KEYCODE_E,"E"),
				new KeyTable(KeyEvent.KEYCODE_F,"F"),
				new KeyTable(KeyEvent.KEYCODE_G,"G"),
				new KeyTable(KeyEvent.KEYCODE_H,"H"),
				new KeyTable(KeyEvent.KEYCODE_I,"I"),
				new KeyTable(KeyEvent.KEYCODE_J,"J"),
				new KeyTable(KeyEvent.KEYCODE_K,"K"),
				new KeyTable(KeyEvent.KEYCODE_L,"L"),
				new KeyTable(KeyEvent.KEYCODE_M,"M"),
				new KeyTable(KeyEvent.KEYCODE_N,"N"),
				new KeyTable(KeyEvent.KEYCODE_O,"O"),
				new KeyTable(KeyEvent.KEYCODE_P,"P"),
				new KeyTable(KeyEvent.KEYCODE_Q,"Q"),
				new KeyTable(KeyEvent.KEYCODE_R,"R"),
				new KeyTable(KeyEvent.KEYCODE_S,"S"),
				new KeyTable(KeyEvent.KEYCODE_T,"T"),
				new KeyTable(KeyEvent.KEYCODE_U,"U"),
				new KeyTable(KeyEvent.KEYCODE_V,"V"),
				new KeyTable(KeyEvent.KEYCODE_W,"W"),
				new KeyTable(KeyEvent.KEYCODE_X,"X"),
				new KeyTable(KeyEvent.KEYCODE_Y,"Y"),
				new KeyTable(KeyEvent.KEYCODE_Z,"Z"),
				new KeyTable(KeyEvent.KEYCODE_COMMA,"COMMA"),
				new KeyTable(KeyEvent.KEYCODE_PERIOD,"PERIOD"),
				new KeyTable(KeyEvent.KEYCODE_ALT_LEFT,"ALT_LEFT"),
				new KeyTable(KeyEvent.KEYCODE_ALT_RIGHT,"ALT_RIGHT"),
				new KeyTable(KeyEvent.KEYCODE_SHIFT_LEFT,"SHIFT_LEFT"),
				new KeyTable(KeyEvent.KEYCODE_SHIFT_RIGHT,"SHIFT_RIGHT"),
				new KeyTable(KeyEvent.KEYCODE_TAB,"TAB"),
				new KeyTable(KeyEvent.KEYCODE_SPACE,"SPACE"),
				new KeyTable(KeyEvent.KEYCODE_SYM,"SYM"),
				new KeyTable(KeyEvent.KEYCODE_EXPLORER,"EXPLORER"),
				new KeyTable(KeyEvent.KEYCODE_ENVELOPE,"ENVELOPE"),
				new KeyTable(KeyEvent.KEYCODE_ENTER,"ENTER"),
				new KeyTable(KeyEvent.KEYCODE_DEL,"DEL"),
				new KeyTable(KeyEvent.KEYCODE_GRAVE,"GRAVE"),
				new KeyTable(KeyEvent.KEYCODE_MINUS,"MINUS"),
				new KeyTable(KeyEvent.KEYCODE_EQUALS,"EQUALS"),
				new KeyTable(KeyEvent.KEYCODE_LEFT_BRACKET,"LEFT_BRACKET"),
				new KeyTable(KeyEvent.KEYCODE_RIGHT_BRACKET,"RIGHT_BRACKET"),
				new KeyTable(KeyEvent.KEYCODE_BACKSLASH,"BACKSLASH"),
				new KeyTable(KeyEvent.KEYCODE_SEMICOLON,"SEMICOLON"),
				new KeyTable(KeyEvent.KEYCODE_APOSTROPHE,"APOSTROPHE"),
				new KeyTable(KeyEvent.KEYCODE_SLASH,"SLASH"),
				new KeyTable(KeyEvent.KEYCODE_AT,"AT"),
				new KeyTable(KeyEvent.KEYCODE_NUM,"NUM"),
				new KeyTable(KeyEvent.KEYCODE_HEADSETHOOK,"HEADSETHOOK"),
				new KeyTable(KeyEvent.KEYCODE_FOCUS,"FOCUS"),
				new KeyTable(KeyEvent.KEYCODE_PLUS,"PLUS"),
				new KeyTable(KeyEvent.KEYCODE_MENU,"MENU"),
				new KeyTable(KeyEvent.KEYCODE_NOTIFICATION,"NOTIFICATION"),
				new KeyTable(KeyEvent.KEYCODE_SEARCH,"SEARCH"),
				new KeyTable(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,"MEDIA_PLAY_PAUSE"),
				new KeyTable(KeyEvent.KEYCODE_MEDIA_STOP,"MEDIA_STOP"),
				new KeyTable(KeyEvent.KEYCODE_MEDIA_NEXT,"MEDIA_NEXT"),
				new KeyTable(KeyEvent.KEYCODE_MEDIA_PREVIOUS,"MEDIA_PREVIOUS"),
				new KeyTable(KeyEvent.KEYCODE_MEDIA_REWIND,"MEDIA_REWIND"),
				new KeyTable(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,"MEDIA_FAST_FORWARD"),
				new KeyTable(KeyEvent.KEYCODE_MUTE,"MUTE"),
				new KeyTable(KeyEvent.KEYCODE_PAGE_UP,"PAGE_UP"),
				new KeyTable(KeyEvent.KEYCODE_PAGE_DOWN,"PAGE_DOWN"),
				new KeyTable(KeyEvent.KEYCODE_PICTSYMBOLS,"PICTSYMBOLS"),
				new KeyTable(KeyEvent.KEYCODE_SWITCH_CHARSET,"SWITCH_CHARSET"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_A,"BUTTON_A"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_B,"BUTTON_B"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_C,"BUTTON_C"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_X,"BUTTON_X"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_Y,"BUTTON_Y"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_Z,"BUTTON_Z"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_L1,"BUTTON_L1"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_R1,"BUTTON_R1"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_L2,"BUTTON_L2"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_R2,"BUTTON_R2"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_THUMBL,"BUTTON_THUMBL"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_THUMBR,"BUTTON_THUMBR"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_START,"BUTTON_START"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_SELECT,"BUTTON_SELECT"),
				new KeyTable(KeyEvent.KEYCODE_BUTTON_MODE,"BUTTON_MODE"),
				new KeyTable(-1,"none")
		};

		public KeyString() {
		}

		public String toName(int icode) {
			int i = 0;
			int ilen = mKeyTable.length;
			
			for(i=0;i<ilen;i++)
			{
				if(icode == mKeyTable[i].code)
				{
					return mKeyTable[i].name;
				}
			}
			
			return "none";
		}
		public int toCode(String name) {
			int i = 0;
			int ilen = mKeyTable.length;
			
			for(i=0;i<ilen;i++)
			{
				if(name.equals(mKeyTable[i].name))
				{
					return mKeyTable[i].code;
				}
			}
			return 999;
		}
	}
	
	public uDebug(){
		sHead = "\u001B[32m\u001B[1m[KMH]\u001B[0m";
		key = new KeyString();
	}
	
	public uDebug(String sh)
	{
		sHead = sh;
	}

	public uDebug(int icolor,String sh)
	{
		sHead = Utils.StringFormat("\u001B[%dm\u001B[1m%s\u001B[0m", icolor,sh);
	}
	
	public static void Config(){
		File flog = new File(uDEF.PathSDCARD_log);
//		if(null == flog){
//			Log.d("uDebug","flog = " + flog.getPath());
//			Log.d("uDebug","fail is_sdcard_mount = " + is_sdcard_mount);
//			return;
//		}
		if(flog.isDirectory()){
			is_sdcard_mount = true;
		}else{
			boolean bresult = flog.mkdirs();
			if(false == bresult){
				Log.e("uDebug","flog = " + flog.getPath());
				Log.e("uDebug","fail is_sdcard_mount = " + is_sdcard_mount);
				return;
			}
			is_sdcard_mount = true;
		}

		cmd_on = Utils.FileExist(uDEF.PathSDCARD_log + "/cmd_on");
//		cmd_on = Utils.hasTestMask(uDEF.MASK_TEST_OPTION_CMD_ON);

		// sdcard unmount test code
		if(true == Utils.FileExist(uDEF.PathSDCARD_log + "/sdcard_unmount")){
			is_sdcard_mount = false;
		}
		
//		if(is_sdcard_mount){
//	    	File file = null;
//	    	file = new File(uDEF.PathSDCARD_log,"log.txt");
//	    	
//	    	if(file.exists()){
//	    		//uDebug udebug = new uDebug("[SIGNAL]");
//	    		boolean bfind_ok = false;
//	    		long lskip_pos = 0;
//	    		String line = null;
//	    		BufferedReader br = null;
//
//	    		lskip_pos = file.length() - 80000;
//	    		if(0 > lskip_pos) lskip_pos = 0;
//	    		
//				String spid = "";
//				spid = Utils.getPID("logcat -v threadtime -f " + file.getAbsolutePath());
//				if(null != spid && 0 < spid.length()){
//					Utils.exec2("busybox kill " + spid);
//				}
//	    		
//	    		try {
//					br = new BufferedReader(new FileReader("/sdcard/metro/log/log.txt"));
//		    		br.skip(lskip_pos);
//		    		while(br.ready()){
//		    			line = br.readLine();
//		    			//bfind_ok = line.matches(".*signal 11.*SIGSEGV.*Player.*");
//		    			bfind_ok = line.matches(".*signal.*");
//
//		    			// PID 가 들어가는 올바른 신호는 skip 한다.
//	    				if (bfind_ok) {
//	    					boolean isPIDsignal = false;
//		    				isPIDsignal = (line.contains("Process") & line.contains("Sending") & line.contains("PID") & line.contains("SIG"));
//		    				if (isPIDsignal) {
//		    					bfind_ok = false;
//		    				}
//		    			}
//
//		    			if(bfind_ok){
//		    				Log.d("[SIGNAL]","");
//		    				Log.d("[SIGNAL]","");
//		    				Log.d("[SIGNAL]",Utils.StringFormat("[%b] %s",bfind_ok,line));
//		    				Log.d("[SIGNAL]","");
//		    				Log.d("[SIGNAL]","");
//
//		    				is_signal_log = true;
//		    				break;
//		    			}
//		    		}
//		    		br.close();
//		    		br = null;
//				} catch (FileNotFoundException e) {
//					e.printStackTrace();
//				} catch (IOException e) {
//					e.printStackTrace();
//				} finally{
//					if(null != br){
//						try {
//							br.close();
//						} catch (IOException e) {
//							e.printStackTrace();
//						}
//						br = null;
//					}
//				}
//	    		
//				if(is_signal_log){
//	    			int postfix = getNextFilePostfix();
//	    			if (LOG_MAX_COUNT <= postfix) {
//	        			deleteFirstLogFile();
//	    			}
//	    			File newfile = new File(uDEF.PathSDCARD_log, Utils.StringFormat("log_%d.txt", postfix));
//	    			if(true == newfile.exists()){
//	    				newfile.delete();
//	    			}
//	    			file.renameTo(newfile);
//				}

//				File saveLogFile = new File(uDEF.PathSDCARD_log, "save_log");
//				if (saveLogFile.exists()) {
//					if (!save_log_off) {
//						save_log_off = false;
//					}
//				} else {
//					if (save_log_off) {
//						save_log_off = true;
//					}
//				}
//	    	}
//		}
	}
	
	public static boolean IsSignalRestart(){
//		return is_signal_log;
		return false;
	}
	
	public static void ToFile(){
		@SuppressWarnings("unused")
		Process process = null;
		
		if(false == is_sdcard_mount){
			Log.e("uDebug","flog = " + uDEF.PathSDCARD_log);
			Log.e("uDebug","is_sdcard_mount = " + is_sdcard_mount);
			return;
		}

		// 한터 로그만 살림
//		if(save_log_off) {
//			Log.e("uDebug", "save_log does not exist, do not save logcat");
//			return;
//		}

//		synchronized (save_logcat) {
//			if (!save_logcat) {
//				if (Utils.FileExist("/sdcard/metro/log/save_logcat")) {
//					save_logcat = true;
//				}
//			}
//
//			if (!mCheckSaveLogcat.isAlive()) {
//				mCheckSaveLogcat.start();
//			}
//
//			if (!save_logcat) {
//				return;
//			}
//		}
/**
		synchronized (dont_save_logcat) {
			if (!dont_save_logcat) {
				if (Utils.FileExist("/sdcard/metro/log/dont_save_logcat")) {
					dont_save_logcat = true;
				}
			}

			if (!mCheckSaveLogcat.isAlive()) {
				mCheckSaveLogcat.start();
			}

			if (dont_save_logcat) {
				return;
			}
		}
*/

	    try {
/**	    	
			Boolean bnewFile = false;
	    	File file = null;
	    	file = new File(uDEF.PathSDCARD_log,"log.txt");
	    	if(true == file.isDirectory()){
	    		file.delete();
	    	}
	    	
	    	if(false == file.exists()){
	    		file.getParentFile().mkdirs();
	    		bnewFile = true;
	    	}else if(true == file.exists()){
	    		if(LOG_SIZE  < file.length()){
//	    			File newfile = new File(uDEF.PathSDCARD_log,"log.txt.bak");
//	    			if(true == newfile.exists()){
//	    				newfile.delete();
//	    			}
//	    			file.renameTo(newfile);
	    			bnewFile = true;
	    		}
	    	}
			
			String spid = "";
			spid = Utils.getPID("logcat -v threadtime -f " + file.getAbsolutePath());
			
			Log.d("PS","---------------------------");
			Log.d("PS","spid = [" + spid + "] logcat -v threadtime -f " + file.getAbsolutePath());
			Log.d("PS",file.getAbsolutePath() + " = " + file.length());
			Log.d("PS","---------------------------");
			
			if(null != spid && 0 < spid.length()){
				if(true == bnewFile){
					Log.d("PS","busybox kill " + spid);
					Runtime.getRuntime().exec("busybox kill " + spid);
					spid = null;
				}
			}

			spid = Utils.getPID("logcat -v threadtime -f " + file.getAbsolutePath());

			Log.d("PS","---------------------------");
			Log.d("PS","spid = [" + spid + "] logcat -v threadtime -f " + file.getAbsolutePath());
			Log.d("PS",file.getAbsolutePath() + " = " + file.length());
			Log.d("PS","---------------------------");

			if(null != spid && 0 < spid.length()){
				if(true == bnewFile){
					Log.d("PS","busybox kill " + spid);
					Runtime.getRuntime().exec("busybox kill " + spid);
					spid = null;
				}
			}

    		if(bnewFile){
    			int postfix = getNextFilePostfix();

    			if (LOG_MAX_COUNT <= postfix) {
        			deleteFirstLogFile();
    			}

    			File newfile = new File(uDEF.PathSDCARD_log, Utils.StringFormat("log_%d.txt", postfix));
    			if(true == newfile.exists()){
    				newfile.delete();
    			}
    			file.renameTo(newfile);
    			Utils.exec("busybox sync");
    		}
			
			if(null == spid || 0 >= spid.length()){
				Runtime.getRuntime().exec("logcat -c");
				Log.d("PS","logcat -v threadtime -f " + file.getAbsolutePath());
				Runtime.getRuntime().exec("logcat -v threadtime -f " + file.getAbsolutePath());

				//Log.d("PS","/system/bin/sh -c cat /proc/kmsg >> " + file.getAbsolutePath());
				//Runtime.getRuntime().exec("/system/bin/sh -c cat /proc/kmsg >> " + file.getAbsolutePath());
				
				//Log.d("PS","/system/bin/sh -c logcat -f /proc/kmsg");
				//Runtime.getRuntime().exec("/system/bin/sh -c logcat -f /proc/kmsg");
				
				//Log.d("PS","busybox cat /proc/kmsg > " + file.getAbsolutePath());
				//Runtime.getRuntime().exec("busybox cat /proc/kmsg > " + file.getAbsolutePath());
				
			}
*/
	    	File getPropFile = null;
	    	final String getPropFileName = "getprop.txt";
	    	getPropFile = new File(uDEF.PathSDCARD_log, getPropFileName);
	    	if(getPropFile.exists()) {
	    		getPropFile.delete();
//    			Utils.exec("busybox sync");
//    			Utils.Sleep(1);
	    	}

	    	getPropFile.createNewFile();

			Utils.exec("busybox sync");
//			Utils.Sleep(1);

			String getprop = Utils.exec("getprop");

			Log.d("PS", "getprop ========================== start\n" + getprop);
			Log.d("PS", "getprop ========================== end");

			FileOutputStream fos = new FileOutputStream(getPropFile);
			fos.write(getprop.getBytes());
			fos.flush();
			fos.close();
			fos = null;
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
/**
	private static void KillLogcat() {
		File file = null;
    	file = new File(uDEF.PathSDCARD_log,"log.txt");

		String spid = Utils.getPID("logcat -v threadtime -f " + file.getAbsolutePath());
		
		Log.d("PS","---------------------------");
		Log.d("PS","spid = [" + spid + "] logcat -v threadtime -f " + file.getAbsolutePath());
		Log.d("PS",file.getAbsolutePath() + " = " + file.length());
		Log.d("PS","---------------------------");
		
		if(null != spid && 0 < spid.length()){
			Log.d("PS","busybox kill " + spid);
			try {
				Runtime.getRuntime().exec("busybox kill " + spid);
			} catch (IOException e) {
				e.printStackTrace();
			}
			spid = null;
		}
		spid = Utils.getPID("logcat");
		
		Log.d("PS","---------------------------");
		Log.d("PS","spid = [" + spid + "] logcat");
		Log.d("PS","---------------------------");
		
		if(null != spid && 0 < spid.length()){
			Log.d("PS","busybox kill " + spid);
			try {
				Runtime.getRuntime().exec("busybox kill " + spid);
			} catch (IOException e) {
				e.printStackTrace();
			}
			spid = null;
		}
		spid = Utils.getPID("logcat");
		
		Log.d("PS","---------------------------");
		Log.d("PS","spid = [" + spid + "] logcat");
		Log.d("PS","---------------------------");
		
		if(null != spid && 0 < spid.length()){
			Log.d("PS","busybox kill " + spid);
			try {
				Runtime.getRuntime().exec("busybox kill " + spid);
			} catch (IOException e) {
				e.printStackTrace();
			}
			spid = null;
		}
	}

	public static void StopLogcat() {
		if (null != mCheckSaveLogcat && mCheckSaveLogcat.isAlive() && !mCheckSaveLogcat.isInterrupted()) {
			mCheckSaveLogcat.interrupt();
			mCheckSaveLogcat = null;
		}
		
		KillLogcat();
	}

	// log_*.txt 파일명을 파싱(*는 숫자)
	private static int getNextFilePostfix() {
		int ipostfix = 0;

		File logDir = new File(uDEF.PathSDCARD_log);
		if (!logDir.isDirectory()) {
			logDir.mkdirs();
			return 1;
		}

		String[] logs = logDir.list();
		if (null != logs) {
			for (String log : logs) {
				Log.d("LOG_MAKE", "log file name : " + log);

				if (!log.contains("log") || !log.contains("txt")) continue;
				if ("log.txt".equals(log)) continue;

				int logNameLen = log.length();
				if (4 < logNameLen) {
					log = log.substring(4, logNameLen);
				}
				logNameLen = log.length();
				if (4 < logNameLen) {
					log = log.substring(0, logNameLen - 4);
				}

				int curInt = 0;
				try {
					curInt = Integer.valueOf(log);
				} catch (NumberFormatException e) {
					e.printStackTrace();
				}

				if (ipostfix < curInt) {
					ipostfix = curInt;
				}
			}
		}

		ipostfix++;

		return ipostfix;
	}

	private static void deleteFirstLogFile() {
		File logDir = new File(uDEF.PathSDCARD_log);
		if (!logDir.isDirectory()) {
			logDir.mkdirs();
			return;
		}

		int minPostfix = -1;

		String[] logs = logDir.list();
		if (null != logs) {
			for (String log : logs) {
				Log.d("LOG_MAKE", "log file name : " + log);

				if (!log.contains("log") || !log.contains("txt")) continue;
				if ("log.txt".equals(log)) continue;
				if ("log.txt.bak".equals(log)) {
					File logbak = new File(uDEF.PathSDCARD_log + File.separator + "log.txt.bak");
					if (logbak.exists()) {
						logbak.delete();
					}
					continue;
				}

				int logNameLen = log.length();
				if (4 < logNameLen) {
					log = log.substring(4, logNameLen);
				}
				logNameLen = log.length();
				if (4 < logNameLen) {
					log = log.substring(0, logNameLen - 4);
				}

				int curInt = 0;
				try {
					curInt = Integer.valueOf(log);
				} catch (NumberFormatException e) {
					e.printStackTrace();
				}

				if (-1 == minPostfix) {
					minPostfix = curInt;
				} else if (minPostfix > curInt) {
					minPostfix = curInt;
				}
			}
		}

		String deleteLog = Utils.StringFormat("log_%d.txt", minPostfix);
		Log.d("uDebug","Delete target file ["+deleteLog+"]");
		File file = new File(uDEF.PathSDCARD_log + File.separator + deleteLog);
		if (file.exists()) {
			Log.d("uDebug","Delete file ["+deleteLog+"]");
			file.delete();
		} else {
			Log.e("uDebug","Can not find deleteLog file ["+deleteLog+"]");
		}
	}
*/
	////////////////////////////////////////////////////////////////////////////////////////////////////////////
	private String tag(String format, Object...args){
		String stime = "";
		if(default_time_on){
			stime = "[" + Utils.stringTime(System.currentTimeMillis()) + "] ";
		}
		return stime + Utils.StringFormat(format, args);
	}
	
	private String msg(String format, Object...args){
		lock.lock();
		String stime = "";
//		if(default_time_on){
//			stime = "[" + Utils.stringTime(ltime) + "] ";
//		}
		String msg = stime + Utils.StringFormat(format, args); 
		lock.unlock();
		return msg;
	}

	private String msg(int color, String format, Object...args){
		lock.lock();
		String stime = "";
//		if(default_time_on){
//			stime = "[" + Utils.stringTime(ltime) + "] ";
//		}
		String msg = Utils.StringFormat("\u001B[%dm\u001B[1m",color) + stime + Utils.StringFormat(format,args) + "\u001B[0m";
		lock.unlock();
		return msg;
	}
	
	public void d(String tag, String format, Object...args)
	{
	
		Log.d(tag(tag) ,msg(format, args));
	}
	
	public void d(int color, String tag, String format, Object...args)
	{
		Log.d(tag(tag) ,msg(color,format, args));
	}
	
	public void v(String tag, String format, Object...args)
	{
		Log.v(tag(tag) ,msg(format, args));
	}
	
	public void v(int color, String tag, String format, Object...args)
	{
		Log.v(tag(tag) ,msg(color,format, args));
	}
	
	public void e(String tag, String format, Object...args)
	{
		Log.e(tag(tag) ,msg(format, args));
	}

	public void e(int color, String tag, String format, Object...args)
	{
		Log.e(tag(tag) ,msg(color,format, args));
	}
	
	public void w(String tag, String format, Object...args)
	{
		Log.w(tag(tag) ,msg(format, args));
	}
	
	public void w(int color, String tag, String format, Object...args)
	{
		Log.w(tag(tag) ,msg(color,format, args));
	}

	public void l(String tag, String format, Object...args)
	{
		d(tag,format,args);
	}

	public void l(int color,String format, Object...args)
	{
		d(color,"",format,args);
	}

	public void second_l(String format, Object...args)
	{
		long lt = SystemClock.uptimeMillis();
		if(1000 < (lt - ltime_one)){
			ltime_one = lt;
			String msg = Utils.StringFormat(format,args);
			d("",msg);
		}
	}
	
	public void Line()
	{
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = "-----------";
		if(1 <= trace.length){
			d(36,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
		}else{
			d(36,"md",msg);
		}
	}
	
	public void InFnc()
	{
//		StackTraceElement[] trace = new Throwable().getStackTrace();
//		String msg = "In";
//		if(1 <= trace.length){
//			d(36,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
//		}else{
//			d(36,"md",msg);
//		}
	}
	
	public void InFnc(String sname)
	{
//		StackTraceElement[] trace = new Throwable().getStackTrace();
//		String msg = "In " + sname;
//		if(1 <= trace.length){
//			d(36,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
//		}else{
//			d(36,"md",msg);
//		}
	}
	
	
	public void OutFnc()
	{
//		StackTraceElement[] trace = new Throwable().getStackTrace();
//		String msg = "Out";
//		if(1 <= trace.length){
//			d(36,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
//		}else{
//			d(36,"md",msg);
//		}
	}

	public void OutFnc(String sname)
	{
//		StackTraceElement[] trace = new Throwable().getStackTrace();
//		String msg = "Out " + sname;
//		if(1 <= trace.length){
//			d(36,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
//		}else{
//			d(36,"md",msg);
//		}
	}
	
	public void dkey(KeyEvent event)
	{
		String smsg="";
		if(null == key){
			key = new KeyString();
		}
		
		switch(event.getAction())
		{
		case KeyEvent.ACTION_DOWN:
			smsg += "ACTION_DOWN ";
			break;
		case KeyEvent.ACTION_UP:
			smsg += "ACTION_UP ";
			break;
		case KeyEvent.ACTION_MULTIPLE:
			smsg += "ACTION_MULTIPLE ";
			break;
		default:
			smsg += "unknown ";
			break;
		}
		
//		d("md","event.getKeyCode() = " + event.getKeyCode());
//		d("md","event.getKeyCode() = " + event.toString());
//		d("md","key = " + key);
		
		smsg += Utils.StringFormat("[%s] = %s", key.toName(event.getKeyCode()),event.toString());
		
		StackTraceElement[] trace = new Throwable().getStackTrace();
		if(1 <= trace.length)
		{
			d(sHead,trace[1].getClassName() + ":" 
					+ trace[1].getMethodName() 
					+ "(" + trace[1].getLineNumber() + "): " + smsg);
		}
		else
		{
			d("md","Out");
		}
	}
	

	public void second_lm(int color, String format, Object...args)
	{
		long lt =SystemClock.uptimeMillis();
		if(1000 < (lt - ltime_one)){
			StackTraceElement[] trace = new Throwable().getStackTrace();
			String msg = Utils.StringFormat(format,args);
			if(1 <= trace.length){
				d(color,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
			}else{
				d(color,"md",msg);
			}
			ltime_one = lt;
		}
	}	
	public void second_lm(String format, Object...args)
	{
		long lt = SystemClock.uptimeMillis();
		if(1000 < (lt - ltime_one)){
			StackTraceElement[] trace = new Throwable().getStackTrace();
			String msg = Utils.StringFormat(format,args);
			if(1 <= trace.length){
				d(sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
			}else{
				d("md",msg);
			}
			ltime_one = lt;
		}
	}
	
	public void lm(String format, Object...args)
	{
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = Utils.StringFormat(format,args);
		if(1 <= trace.length){
			d(sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
			//System.out.println(trace[1].getMethodName()+"(" + trace[1].getLineNumber() + "):" + msg);
		}else{
			d("md",msg);
		}
	}
	

	public void lm(int color,String format, Object...args)
	{
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = Utils.StringFormat(format,args);
		if(1 <= trace.length){
			d(color,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
			//System.out.println(trace[1].getMethodName()+"(" + trace[1].getLineNumber() + "):" + msg);
		}else{
			d(color,"md",msg);
		}
	}

	public void error(String format, Object...args)
	{
		int color = 31;
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = Utils.StringFormat(format,args);
		if(1 <= trace.length){
			e(31,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
		}else{
			e(31,"md",msg);
		}
	}

	public void warn(String format, Object...args)
	{
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = Utils.StringFormat(format,args);
		if(1 <= trace.length){
			w(sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
		}else{
			w("md",msg);
		}
	}

	public void warn(int color, String format, Object...args)
	{
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = Utils.StringFormat(format,args);
		if(1 <= trace.length){
			w(color,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
		}else{
			w(color,"md",msg);
		}
	}
	
	public void hm(String format, Object...args)
	{
		String msg = Utils.StringFormat(format,args);
		d(sHead,msg);
	}

	public void hm(int color,String format, Object...args)
	{
		String msg = Utils.StringFormat(format,args);
		d(color,sHead ,msg);
	}	
	

	public void m(String format, Object...args)
	{
		String msg = Utils.StringFormat(format,args);
		d("",msg);
	}
	
	public void m(int color,String format, Object...args)
	{
		String msg = Utils.StringFormat(format,args);
		d(color,"" ,msg);
	}	

	public void cmd(int color,String format, Object...args)
	{
		if(false == cmd_on) return;
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = Utils.StringFormat(format,args);
		if(1 <= trace.length){
			d(color,sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
		}else{
			d(color,"md",msg);
		}
	}
	
	public void cmd(String format, Object...args)
	{
		if(false == cmd_on) return;
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = Utils.StringFormat(format,args);
		if(1 <= trace.length){
			d(sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
		}else{
			d("md",msg);
		}
	}
		
	public void tlm(String format, Object...args)
	{
		long ltime = System.currentTimeMillis();
		
		NumberFormat nf = NumberFormat.getInstance();
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = Utils.StringFormat(format,args);
		String stime = "[" + Utils.stringTime(ltime) + "]";
		if(1 <= trace.length){
			d(stime + sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
		}else{
			d("md",msg);
		}
	}
	
	public void tlm(int color, String format, Object...args)
	{
		long ltime = System.currentTimeMillis();
		
		NumberFormat nf = NumberFormat.getInstance();
		StackTraceElement[] trace = new Throwable().getStackTrace();
		String msg = Utils.StringFormat(format,args);
		String stime = "[" + Utils.stringTime(ltime) + "]";
		if(1 <= trace.length){
			d(color,stime + sHead ,trace[1].getClassName() + ":" +  trace[1].getMethodName() + "(" + trace[1].getLineNumber() + "): " + msg);
		}else{
			d(color,"md",msg);
		}
	}
}
