package com.backfire.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import android.os.Environment;

/**
 * Wrapper of android.util.Log.<br>
 * 支持写到文件 sdcard/backfire/log.txt<br>
 */
/**
 * @author wf
 *
 */
public class Log {

	public static final int LOG_WRITEFILE = 0x0001;
	public static final int LOG_VERBOSE = 0x0002;
	public static final int LOG_INFO = 0x0004;
	public static final int LOG_WARNING = 0x0008;
	public static final int LOG_DEBUG = 0x0010;
	public static final int LOG_ERROR = 0x0020;

	private static byte[] syncLock = new byte[0];
	private static final String LOG_STRIP = " ";
	private static final String LOG_FILE = "log";
	private static final String LOG_PATH = "backfire";
	private static final String DOT = ".";
	private static String fullPath;
	private static final int num = 10;
	private static int sequence;

	public static int debug_level = 1;

	private static void createFile(String name) {
		File file = new File(name);
		if (file.exists())
			return;
		try {
			file.createNewFile();
		} catch (IOException e) {
		}
	}

	public static String getSDLogPath() {
		return Environment.getExternalStorageDirectory().getAbsolutePath()
				+ File.separator + LOG_PATH;
	}
	
	public static String getAppLogPath(String dir) {

		return dir + File.separator + LOG_PATH;
	}

	public static boolean testSDCard() {
		boolean flag = false;
		if (android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED)) {
			flag = true;
		}
		return flag;
	}

	public static void init(String dir) {
		sequence = 0;
		
		if (testSDCard()) {
			String str = getSDLogPath();
			File file = new File(str);
			
			boolean flag = true;
			
			if(!file.exists())
			{
				flag = file.mkdir();
			}

			if (!flag) {
				android.util.Log.e("error", "mkdir error");
			}
			long runtime = Calendar.getInstance().getTimeInMillis();
			fullPath = str + File.separator + LOG_FILE + DOT + runtime+".txt";
			createFile(fullPath);
		} else {
			String str = getAppLogPath(dir);
			File file = new File(str);
			file.mkdir();
			fullPath = str + File.separator + LOG_FILE;
			createFile(fullPath);
		}
        //初始化Log级别
		debug_level = LOG_WRITEFILE|LOG_VERBOSE|LOG_INFO|LOG_WARNING|LOG_DEBUG|LOG_ERROR;
	}

	public static String catInfo(String info) {

		StringBuilder sb = new StringBuilder();
		sb.append(String.format("[seq=%08d] [ThreadID=%04d]", sequence++,
				Thread.currentThread().getId()));

		sb.append(LOG_STRIP);
		sb.append(info);
		return sb.toString();
	}

	public static String catInfoE(String info, Throwable e) {

		StringBuilder sb = new StringBuilder();
		sb.append(String.format("[seq=%08d] [ThreadID=%04d]", sequence++,
				Thread.currentThread().getId()));

		sb.append(LOG_STRIP);
		sb.append(info);
		sb.append(LOG_STRIP);
		sb.append(Debug.genStackTrace(e));
		return sb.toString();
	}

	public static void v(Object obj, String info) {

		if ( 0==(debug_level & LOG_VERBOSE))return;
		info = catInfo(info);
		android.util.Log.v(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void e(Object obj, String info) {
		if ( 0==(debug_level & LOG_ERROR))return;
		info = catInfoE(info, new Throwable());
		android.util.Log.e(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void i(Object obj, String info) {
		if ( 0==(debug_level & LOG_INFO))return;
		info = catInfo(info);
		android.util.Log.i(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void d(Object obj, String info) {
		if ( 0==(debug_level & LOG_DEBUG))return;
		info = catInfo(info);
		android.util.Log.d(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void w(Object obj, String info) {
		if ( 0==(debug_level & LOG_WARNING))return;
		info = catInfo(info);
		android.util.Log.w(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void v(int pos, Object obj, String info) {
		if ( 0==(debug_level & LOG_VERBOSE))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfo(info);
		android.util.Log.v(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
		Log.LogFile(pos, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void e(int pos, Object obj, String info) {
		if ( 0==(debug_level & LOG_ERROR))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfoE(info, new Throwable());
		android.util.Log.e(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
		Log.LogFile(pos, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void i(int pos, Object obj, String info) {
		if ( 0==(debug_level & LOG_INFO))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfo(info);
		android.util.Log.i(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
		Log.LogFile(pos, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void d(int pos, Object obj, String info) {
		if ( 0==(debug_level & LOG_DEBUG))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfo(info);
		android.util.Log.d(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
		Log.LogFile(pos, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void w(int pos, Object obj, String info) {
		if ( 0==(debug_level & LOG_WARNING))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfo(info);
		android.util.Log.w(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
		Log.LogFile(pos, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void e(Object obj, Exception e) {
		if ( 0==(debug_level & LOG_ERROR))return;
		String info = Debug.genStackTrace(e);
		info = catInfo(info);
		android.util.Log.e(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void e(int pos, Object obj, Exception e) {
		if ( 0==(debug_level & LOG_ERROR))return;
		if (pos < -1 || pos >= num)
			return;
		String info = Debug.genStackTrace(e);
		info = catInfo(info);
		android.util.Log.e(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
		Log.LogFile(pos, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void v(String name, String info) {
		if ( 0==(debug_level & LOG_VERBOSE))return;
		info = catInfo(info);
		android.util.Log.v(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void e(String name, String info) {
		if ( 0==(debug_level & LOG_ERROR))return;
		info = catInfoE(info, new Throwable());
		android.util.Log.e(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void i(String name, String info) {
		if ( 0==(debug_level & LOG_INFO))return;
		info = catInfo(info);
		android.util.Log.i(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void d(String name, String info) {
		if ( 0==(debug_level & LOG_DEBUG))return;
		info = catInfo(info);
		android.util.Log.d(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void w(String name, String info) {
		if ( 0==(debug_level & LOG_WARNING))return;
		info = catInfo(info);
		android.util.Log.w(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void v(int pos, String name, String info) {
		if ( 0==(debug_level & LOG_VERBOSE))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfo(info);
		android.util.Log.v(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
		Log.LogFile(pos, name + LOG_STRIP + info);
	}

	public static void e(int pos, String name, String info) {
		if ( 0==(debug_level & LOG_ERROR))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfoE(info, new Throwable());
		android.util.Log.e(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
		Log.LogFile(pos, name + LOG_STRIP + info);
	}

	public static void i(int pos, String name, String info) {
		if ( 0==(debug_level & LOG_INFO))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfo(info);
		android.util.Log.i(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
		Log.LogFile(pos, name + LOG_STRIP + info);
	}

	public static void d(int pos, String name, String info) {
		if ( 0==(debug_level & LOG_DEBUG))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfo(info);
		android.util.Log.d(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
		Log.LogFile(pos, name + LOG_STRIP + info);
	}

	public static void w(int pos, String name, String info) {
		if ( 0==(debug_level & LOG_WARNING))return;
		if (pos < -1 || pos >= num)
			return;
		info = catInfo(info);
		android.util.Log.w(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
		Log.LogFile(pos, name + LOG_STRIP + info);
	}

	public static void v(String name, Exception e) {
		if ( 0==(debug_level & LOG_VERBOSE))return;
		String info = Debug.genStackTrace(e);
		info = catInfo(info);
		android.util.Log.v(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void e(String name, Exception e) {
		if ( 0==(debug_level & LOG_ERROR))return;
		String info = Debug.genStackTrace(e);
		info = catInfo(info);
		android.util.Log.e(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void i(String name, Exception e) {
		if ( 0==(debug_level & LOG_INFO))return;
		String info = Debug.genStackTrace(e);
		info = catInfo(info);
		android.util.Log.i(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void d(String name, Exception e) {
		if ( 0==(debug_level & LOG_DEBUG))return;
		String info = Debug.genStackTrace(e);
		info = catInfo(info);
		android.util.Log.d(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void w(String name, Exception e) {
		if ( 0==(debug_level & LOG_WARNING))return;
		String info = Debug.genStackTrace(e);
		info = catInfo(info);
		android.util.Log.w(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
	}

	public static void e(int pos, String name, Exception e) {
		if ( 0==(debug_level & LOG_ERROR))return;
		if (pos < -1 || pos >= num)
			return;
		String info = Debug.genStackTrace(e);
		info = catInfo(info);
		android.util.Log.e(name, info);
		Log.LogFile(-1, name + LOG_STRIP + info);
		Log.LogFile(pos, name + LOG_STRIP + info);
	}

	// support ... parameters

	public static String catInfo(Object... objects) {
		StringBuilder sb = new StringBuilder();
		sb.append(String.format("[seq=%08d] [ThreadID=%04d]", sequence++,
				Thread.currentThread().getId()));
		sb.append(LOG_STRIP);
		for (Object obj : objects) {
			sb.append(String.valueOf(obj)).append(LOG_STRIP);
		}

		return sb.toString();
	}

	public static void v(Object obj, Object... objects) {
		if ( 0==(debug_level & LOG_VERBOSE))return;
		String info = catInfo(objects);
		android.util.Log.v(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void e(Object obj, Object... objects) {
		if ( 0==(debug_level & LOG_ERROR))return;
		String info = catInfo(objects);
		android.util.Log.e(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void i(Object obj, Object... objects) {
		if ( 0==(debug_level & LOG_INFO))return;
		String info = catInfo(objects);
		android.util.Log.i(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void d(Object obj, Object... objects) {
		if ( 0==(debug_level & LOG_DEBUG))return;
		String info = catInfo(objects);
		android.util.Log.d(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	public static void w(Object obj, Object... objects) {
		if ( 0==(debug_level & LOG_WARNING))return;
		String info = catInfo(objects);
		android.util.Log.w(obj.getClass().getName(), info);
		Log.LogFile(-1, obj.getClass().getName() + LOG_STRIP + info);
	}

	private static SimpleDateFormat dformat = new SimpleDateFormat(
			"yyyy-MM-dd HH:mm:ss SSS");

	private static void LogFile(int pos, String info) {
		if ((debug_level & LOG_WRITEFILE) > 0) {
			synchronized (Log.syncLock) {
				try {
					File file;
					if (pos < 0) {
						file = new File(fullPath);
					} else {
						file = new File(fullPath + DOT + pos);
					}
					FileOutputStream fos = new FileOutputStream(file, true);
					info = dformat.format(Calendar.getInstance().getTimeInMillis())
							+ LOG_STRIP + info;
					fos.write(info.getBytes());
					fos.write('\n');
					fos.close();
				} catch (IOException ex) {
				}
			}
		}	
	}
}
