package com.gh.common.util;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.TrafficStats;

import java.util.Calendar;
import java.util.List;

public class TrafficUtils {

	static TrafficUtils instance;
	DB db;
	Context context;

	public static TrafficUtils getInstance(Context context) {
		return getInstance(context, false);
	}
	
	public static TrafficUtils getInstance(Context context, boolean update) {
		if (instance == null) {
			synchronized (TrafficUtils.class) {
				if (instance == null) {
					instance = new TrafficUtils(context);
					if (update)
						instance.update();
					return instance;
				}
			}
		}
		if (update)
			instance.update();
		return instance;
	}

	private TrafficUtils(Context context) {
		this.context = context.getApplicationContext();
		db = new DB(this.context);
	}

	public void update() {

		// 获取所有的安装在手机上的应用软件的信息，并且获取这些软件里面的权限信息
		PackageManager pm = context.getPackageManager();// 获取系统应用包管理
		// 获取每个包内的androidmanifest.xml信息，它的权限等等
		List<PackageInfo> pinfos = pm
				.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES
						| PackageManager.GET_PERMISSIONS);
		// 遍历每个应用包信息
		for (PackageInfo info : pinfos) {
			// 请求每个程序包对应的androidManifest.xml里面的权限
			String[] premissions = info.requestedPermissions;
			if (premissions != null && premissions.length > 0) {
				// 找出需要网络服务的应用程序
				for (String premission : premissions) {
					if ("android.permission.INTERNET".equals(premission)) {
						// 获取每个应用程序在操作系统内的进程id
						int uId = info.applicationInfo.uid;
						// 如果返回-1，代表不支持使用该方法，注意必须是2.2以上的
						long rx = TrafficStats.getUidRxBytes(uId);
						// 如果返回-1，代表不支持使用该方法，注意必须是2.2以上的
						long tx = TrafficStats.getUidTxBytes(uId);
						if (rx < 0 || tx < 0) {
							continue;
						} else {
							db.update(info.packageName, rx + tx);
						}
					}
				}
			}
		}

		db.clean(Calendar.getInstance().getTimeInMillis() - 3600 * 24 * 30);
	}

	public long getTraffic(List<String> packageNameList) {
		return this.getTraffic(packageNameList, Calendar.getInstance()
				.getTimeInMillis() - 3600 * 24 * 7);
	}

	public long getTraffic(List<String> packageNameList, long from) {
		return this.getTraffic(packageNameList, from, Calendar.getInstance()
				.getTimeInMillis());
	}

	public long getTraffic(List<String> packageNameList, long from, long to) {
		long traffic = 0;
		for (String packageName : packageNameList) {
			traffic += db.getTraffic(packageName, from, to);
		}
		return traffic;
	}
	
	public long getTraffice(String packageName){
		return db.getTraffic(packageName, Calendar.getInstance()
				.getTimeInMillis() - 3600 * 24 * 7);
	}
	
	public long getTraffice(String packageName, long from){
		return db.getTraffic(packageName, from);
	}

	class DB extends SQLiteOpenHelper {

		static final String name = "gh_traffic.db";
		static final int version = 1;

		public DB(Context context) {
			super(context, name, null, version);
		}

		String traffic = "CREATE TABLE traffic(" + "package text,"
				+ "traffic integer not null," + "time integer not null" + ");";

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL(traffic);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		}

		public void update(String packageName, long traffic) {
			String sql = "INSERT INTO traffic (package, traffic, time) VALUES (?, ?, ?)";
			Object[] bindArgs = new Object[] { packageName, traffic,
					Calendar.getInstance().getTimeInMillis() };
			this.getWritableDatabase().execSQL(sql, bindArgs);
		}

		public void clean(long time) {
			String sql = "DELETE FROM traffic WHERE time < ? ";
			Object[] bindArgs = new Object[] { time };
			this.getWritableDatabase().execSQL(sql, bindArgs);
		}

		public long getTraffic(String packageName, long from) {
			return getTraffic(packageName, from, Calendar.getInstance()
					.getTimeInMillis());
		}

		public long getTraffic(String packageName, long from, long to) {
			long traffic = 0;
			String sql = "SELECT * FROM traffic WHERE package = ? AND time >= ? AND time <= ? ORDER BY time DESC";
			String selectionArgs[] = new String[] { packageName,
					String.valueOf(from), String.valueOf(to) };
			Cursor cursor = this.getReadableDatabase().rawQuery(sql,
					selectionArgs);
			if (cursor.getCount() > 1) {
				cursor.moveToFirst();
				long traffic1 = cursor
						.getLong(cursor.getColumnIndex("traffic"));
				// long time1 = cursor.getLong(cursor.getColumnIndex("time"));
				cursor.moveToLast();
				long traffic2 = cursor
						.getLong(cursor.getColumnIndex("traffic"));
				// long time2 = cursor.getLong(cursor.getColumnIndex("time"));
				traffic = traffic1 - traffic2;
				// long cha = traffic1 - traffic2;
				// if(cha > 0){
				// traffic = cha / (time2 - time1);
				// }
			} else if (cursor.getCount() == 1) {
				sql = "SELECT * FROM traffic WHERE package = ? AND time < ? ORDER BY time DESC";
				selectionArgs = new String[] { packageName,
						String.valueOf(from) };
				Cursor cursor2 = this.getReadableDatabase().rawQuery(sql,
						selectionArgs);
				if (cursor2.moveToNext()) {
					cursor.moveToFirst();
					long traffic1 = cursor.getLong(cursor
							.getColumnIndex("traffic"));
					// long time1 =
					// cursor.getLong(cursor.getColumnIndex("time"));
					long traffic2 = cursor2.getLong(cursor
							.getColumnIndex("traffic"));
					// long time2 =
					// cursor2.getLong(cursor.getColumnIndex("time"));
					traffic = traffic1 - traffic2;
					// long cha = traffic1 - traffic2;
					// if(cha > 0){
					// traffic = cha / (time2 - time1);
					// }
				}
				cursor2.close();
			}
			cursor.close();
			return traffic;
		}
	}
}
