package com.imofan.android.basic;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.telephony.TelephonyManager;

import com.imofan.android.basic.LocationService.LocationResult;
import com.imofan.android.basic.LocationService.LocationSuccessListener;
import com.imofan.android.basic.notification.MFPreferencesUtils;
 /**
  * 
  * 网速统计
  * @author user
  */
public class MFNetSpeedMonitor {
	/* 抽样指令 */
	private static final String uri = "http://mga.imofan.com/service/netspeed.jsp";
	
	/* 抽样监控状态,默认打开 */ 
	private static boolean recordStatus = true;
	
	/*  是否监控图片下载 */
	private static boolean isRecordImage = true;
	
	/* 需要统计的上限 ，默认值为50 */
	private static int maxLimit = 50;
	
	/* 应用启动时间 */
	private static String appStartTime;
	
	/* 存储批次时间，应用启动时间(依赖魔方的启动规则) */
	private static final String MATCH_TIME = "match_time";
	
	/* 地区 */
	private static final String AREA_INFO = "area_info";
	
	/* 存储任务开始时间 */
	private static ConcurrentHashMap<String, Long>  maps = new ConcurrentHashMap<String, Long>();
	
    //http请求
    private static final int HTTP = 0x0;
    //网页请求
    private static final int WEB =  0x1;
	
    //客户端是否需要打开网速监测
    private static boolean isOpenmonitor = false;
    
    public static void setMonitorEnable(boolean isOpen){
    	isOpenmonitor = isOpen;
    }
    
	/**
	 * 初始化地区 【"省,市"】应用启动时候执行，获取地区信息，方便对网络数据进行统计与分析
	 * @param context
	 * @param pro
	 * @param city
	 */
	static void initCurrentArea(final Context context){
		if(!isOpenmonitor) return;
		LocationService.startLocation(context, new LocationSuccessListener() {
			@Override
			public void onLocationResult(LocationResult result) {
				String pro = result.getProvince();
				String city = result.getCity();
				if(null!=pro && !"".equals(pro) && null!=city && !"".equals(city)){
				    if(pro.indexOf("省")>-1){
				        pro = pro.substring(0, pro.indexOf("省"));
				    }
				    if(pro.indexOf("市")>-1){
		                pro = pro.substring(0, pro.indexOf("市"));
		            }
				    if(city.indexOf("市")>-1){
				        city = city.substring(0, city.indexOf("市"));
		            }
					MFPreferencesUtils.setPreferences(context, AREA_INFO, "area", pro+","+city);
					getRecordInfo(context,Uri.encode(pro, "utf-8")+","+Uri.encode(city, "utf-8"));
				}else{
					recordStatus = false;
					updateRecordInfo(context,recordStatus);
				}
			}
		});
	}
	
	
	static void updateRecordInfo(Context context,boolean recordStatus){
		MFAPPBasicInfo.updateRecordInfo(Mofang.dbManager, getStartTime(context), recordStatus, maxLimit, isRecordImage);
	}
	
	/**
	 * app启动时记录启动时间,依赖魔方新启动应用的规则
	 * @param context
	 */
	static void recordStartTime(Context context){
		if(!isOpenmonitor) return;
		Date date = new Date();  
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");  
		appStartTime = dateFormat.format(date);
		MFPreferencesUtils.setPreferences(context, MATCH_TIME, "start_time", appStartTime);
		if(Mofang.dbManager == null) {
			Mofang.dbManager = MFDatabaseManager.getInstance(context);
        }
		MFAPPBasicInfo.addAppInfo(context, Mofang.dbManager, getAreaInfo(context), appStartTime);
	}
	
	static String getAreaInfo(Context context){
		return MFPreferencesUtils.getPreference(context, AREA_INFO, "area", "");
	}
	
	static String getStartTime(Context context){
	    return MFPreferencesUtils.getPreference(context, MATCH_TIME, "start_time", "");
	}
	
	/**
	 * 任务开启
	 * @param context
	 * @param uri
	 */
	public static void start(Context context,String uri){
		if(!isOpenmonitor) return;
		if(!recordStatus) return;
		if(null!=uri && !"".equals(uri)){
			maps.put(uri, System.currentTimeMillis());
		}
	}
	
	 /**
	  * 任务结束
	  * @param context
	  * @param uri
	  * @param isWebView     是否是webview加载资源
	  * @param isImageType   下载资源类型是否是图片
	  * @param length		 下载回来资源的大小
	  * @param statusCode    下载返回状态码
	  */
	 private static void end(Context context,String uri,boolean isWebView,boolean isImageType,long length,int statusCode){
		if(!isOpenmonitor) return;
		//如果不需要监测
		if(!recordStatus) return;
		//如果图片不需抽样
		if(!isRecordImage && isImageType) return;
		if(maps==null) return; 
		long startTime = 0;
		if(uri!=null && !"".equals(uri)){
			startTime = maps.get(uri)==null ? 0 : maps.get(uri);
		}
		if(startTime==0) return;
		//计算下载资源文件耗费的时间
		long durationTime = System.currentTimeMillis()-startTime;
		if(Mofang.dbManager == null) {
			Mofang.dbManager = MFDatabaseManager.getInstance(context);
		}
		
		//根据每次启动时间获取应用信息，级联表进行数据填充，以及主表地区信息未初始化时，再次进行填充
		MFAPPBasicInfo appInfo = MFAPPBasicInfo.getAppInfoByTime(Mofang.dbManager, appStartTime);
		int id = 0;
		if(appInfo!=null){
			id= appInfo.getId();
			String region = appInfo.getRegion();
			if(region==null || "".equals(region)){
				//根据当前id更新表中的地区信息
				MFAPPBasicInfo.updateAppInfo(Mofang.dbManager, String.valueOf(id), getAreaInfo(context));
			}
			//存储
			MFNetworkInfo.addNetworkInfo(context, Mofang.dbManager,getRequestType(isWebView), uri,startTime, isImageType,length, durationTime,statusCode,id);
		}
		maps.remove(uri);
	}
	
	/**
	 * http请求调用 
	 * @param context
	 * @param uri
	 * @param isImageType
	 * @param length
	 * @param statusCode
	 */
	public static void end(Context context,String uri,boolean isImageType,long length,int statusCode){
		if(!isOpenmonitor) return;
		if(uri==null || "".equals(uri)) return;
		end(context,uri,false,isImageType,length,statusCode);
	}
	
	/**
	 * webview调用
	 * @param context
	 * @param uri
	 * @param isWebView
	 * @param isImageType
	 * @param length
	 * @param statusCode
	 */
	public static void webViewEnd(Context context,String uri,int statusCode){
		if(!isOpenmonitor) return;
		if(uri==null || "".equals(uri)) return;
		end(context,uri,true,false,0,statusCode);
	}
	
	/**
	 * 根据uri判断请求类型
	 * @param uri
	 * @return
	 */
	private static int getRequestType(boolean isWebView){
		if(isWebView){
			return WEB;
		}
	    return HTTP;
	}
	
	/**
	 * 清除监控数据表，已经发送和冗余数据
	 * @param context
	 */
	public static void clearData(MFDatabaseManager dbManager,List<Integer> ids){
		MFAPPBasicInfo.clearData(dbManager,ids);
	}
	
	/**
	 * 
	 * @return
	 */
	static NetspeedData generateSendData(Context context,MFDatabaseManager dbManager){
		JSONArray jsonArray = new JSONArray();
		NetspeedData netspeedData = new NetspeedData();
		List<Integer> ids = null;
		List<MFAPPBasicInfo> basicDatas = MFAPPBasicInfo.getMFappBasicInfos(dbManager, getStartTime(context)); 
		if(null!=basicDatas ){
		    ids = new ArrayList<Integer>();
		    String region;
		    String access;
		    String carrier;
		    int max;
		    boolean isRecordImage;
		    List<MFNetworkInfo> netdatas;
		    JSONArray datas = null;
			for(MFAPPBasicInfo basicInfo : basicDatas){
			    region = basicInfo.getRegion();
			    carrier = basicInfo.getCarrier();
			    int id = basicInfo.getId();
			    ids.add(id);
			    max = basicInfo.getMax();
			    isRecordImage = basicInfo.isRecoImage();
			    netdatas = MFNetworkInfo.getNetworkInfo(dbManager, id);
			    if(null!=netdatas){
			        int size = netdatas.size();
			        if(size >= max) size = max;
			        //下载资源是否是图片
			        boolean isImageType;
			        for(int i=0;i<size;i++){
			            datas = new JSONArray();
			            isImageType = netdatas.get(i).isImageType();
			            //如果不需要图片抽样数据，且这个下载是图片的时候，不生成该数据
			            if(!isRecordImage && isImageType) continue;
			            datas.put(netdatas.get(i).getType());
			            datas.put(netdatas.get(i).getUrl());
			            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
			            datas.put(Long.valueOf(dateFormat.format(netdatas.get(i).getStartTime())));
			            datas.put(region);
			            access = netdatas.get(i).getAccess().toLowerCase();
			            datas.put(carrier+","+access);
			            datas.put(netdatas.get(i).getStatusCode());
			            datas.put(netdatas.get(i).getSize());
			            datas.put(netdatas.get(i).getDuration());
			            
//			            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
//			            datas.put("开始时间: "+df.format(netdatas.get(i).getStartTime()));
//			            
//			            SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
//			            datas.put("结束时间: "+df1.format(netdatas.get(i).getStartTime()+netdatas.get(i).getDuration()));
			            
			            jsonArray.put(datas);
			        }
			        
			    }
			}
			
		}
		
		if(Mofang.DEBUG){
//		Log.v("ly", "==="+jsonArray.toString());
			LogUtils.writeLog(jsonArray.toString());
		}
		
        netspeedData.setIdList(ids);
        netspeedData.setJsonArray(jsonArray);
		
		return netspeedData;
	}	
	
	
	/**
	 * 获取抽样指令（每次应用正常启动时获取一次，不经常修改的配置）
	 * @param context
	 */
	private static void getRecordInfo(final Context context,String region){
		//PUBLISH CHECK 上线之前让魔方把抽样指令关掉
		final String dataString = uri + "?appKey="+Mofang.getAppKey(context) + 
				"&deviceId=" + Mofang.getDevId(context) + 
				"&mac=" + getDeviceMac(context) + 
				"&region="+ region + 
				"&carrier="+Uri.encode(getCarrierName(context),"utf-8")+
				"&access="+getNetworkType(context);
		new Thread(new Runnable() {
			@Override
			public void run() {
				HttpURLConnection urlConnection = null;
				InputStream in = null;
				StringBuffer strbuffer = null;
				BufferedReader reader = null;
				
				try {
					final URL url = new URL(dataString);
					urlConnection = (HttpURLConnection)url.openConnection();
					in = urlConnection.getInputStream();
					if(null==in) return;
					strbuffer = new StringBuffer();
					String line;
					reader = new BufferedReader(new InputStreamReader(in));
					while((line = reader.readLine()) != null) {
						strbuffer.append(line).append("\r\n");
					}
					
					JSONObject jsonObject = new JSONObject(strbuffer.toString());
					//是否监控
					recordStatus = jsonObject.optBoolean("record");
					//需要抽样的最大限制
					maxLimit = jsonObject.optInt("max");
					//是否抽样监控图片下载
					isRecordImage = jsonObject.optBoolean("image");
				    if(Mofang.dbManager == null) {
				        Mofang.dbManager = MFDatabaseManager.getInstance(context);
			        }
					
				    updateRecordInfo(context,recordStatus);
					
				} catch (final IOException e) {
					e.printStackTrace();
					recordStatus = false;
					updateRecordInfo(context,recordStatus);
				}catch(JSONException e){
				    e.printStackTrace();
					recordStatus = false;
				    updateRecordInfo(context,recordStatus);
				}catch(Exception e){
				    e.printStackTrace();
				    recordStatus = false;
				    updateRecordInfo(context,recordStatus);
				} finally {
				    if(reader != null) {
				        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
					if (urlConnection != null) {
						urlConnection.disconnect();
					}
					try {
						if (in != null) {
							in.close();
						}
					} catch (final IOException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
	
    public static String hashKey(String key) {
        String cacheKey;
        try {
            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytesToHexString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }
    
    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }
	
    
	/**
	 * 转换器 
	 * @param d
	 * @param isFormatTime  是否转换时间
	 * @return
	 */
    static DecimalFormat decimalFormat;
	static String format(long d,boolean isFormatTime){
	    String pattern;
	    int scale;
	    if(isFormatTime){
	        scale = 1000;
	        pattern = "###.###";
	    }else{
	        scale = 1024;
	        pattern = "###.#####";
	    }
	    decimalFormat =new DecimalFormat(pattern);
	    float data  = (float) ((float) d / (float) scale);
	    return (decimalFormat.format(new Float(data).floatValue()));
	}
	
	/**
	 * 获取网络类型
	 * @param context
	 * @return
	 */
	private static String getNetType(Context context){
		ConnectivityManager connectionManager = (ConnectivityManager)      
                context.getSystemService(Context.CONNECTIVITY_SERVICE);   
		if(connectionManager!=null){
			NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();
			if(null!=networkInfo){
				return networkInfo.getTypeName().toLowerCase();
			}
		}
		return "none";
	}
	/**
	 *  GPRS       2G(2.5) General Packet Radia Service 114kbps
	 *	EDGE       2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps
	 *	UMTS      3G WCDMA 联通3G Universal Mobile Telecommunication System 完整的3G移动通信技术标准
     *	CDMA     2G 电信 Code Division Multiple Access 码分多址
		EVDO_0   3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于3G
		EVDO_A  3G 1.8mbps - 3.1mbps 属于3G过渡，3.5G
		1xRTT      2G CDMA2000 1xRTT (RTT - 无线电传输技术) 144kbps 2G的过渡,
		HSDPA    3.5G 高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps 
		HSUPA    3.5G High Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps
		HSPA      3G (分HSDPA,HSUPA) High Speed Packet Access 
		IDEN      2G Integrated Dispatch Enhanced Networks 集成数字增强型网络 （属于2G，来自维基百科）
		EVDO_B 3G EV-DO Rev.B 14.7Mbps 下行 3.5G
		LTE        4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G过渡，升级版 LTE Advanced 才是4G 
		EHRPD  3G CDMA2000向LTE 4G的中间产物 Evolved High Rate Packet Data HRPD的升级
		HSPAP  3G HSPAP 比 HSDPA 快些
	 * @param context
	 * @return
	 */
	 static String getNetworkType(Context context) {
		 String type="";
	     TelephonyManager telephonyManager = null;
	     try{
	    	 telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
	    	 int networkType = telephonyManager.getNetworkType();
	    	 
	    	 if(getNetType(context).equals("wifi")){
	    		 type = "wifi";
	    	 }
	    	 
	    	 else if(networkType ==TelephonyManager.NETWORK_TYPE_LTE){
	    		 type = "4g";
	    	 }
	    	 else if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
	    			 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
	    			 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
	    			 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
	    			 || networkType == TelephonyManager.NETWORK_TYPE_EVDO_0
	    			 || networkType == TelephonyManager.NETWORK_TYPE_EVDO_A
	    			 || networkType == TelephonyManager.NETWORK_TYPE_EHRPD
	    			 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP
	    			 ) {
	    		 type = "3g";
	    	 } 
	    	 else if (networkType == TelephonyManager.NETWORK_TYPE_GPRS
	    			 || networkType == TelephonyManager.NETWORK_TYPE_EDGE
	    			 || networkType == TelephonyManager.NETWORK_TYPE_CDMA
	    			 || networkType == TelephonyManager.NETWORK_TYPE_1xRTT
	    			 || networkType == TelephonyManager.NETWORK_TYPE_IDEN) {
	    		 type = "2g";
	    	 }
	    	 else{
	    		 type = "none";
	    	 }
	     }catch(Exception e){
	    	 e.printStackTrace();
	     }
		 return type;
	}	
	
	/**
	 * 获取运营商
	 * @param context
	 * @return
	 */
	static String getCarrierName(Context context){
		TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
		if(telephonyManager != null) {
            String imsi = telephonyManager.getSubscriberId();
            if(imsi != null && imsi.trim().length() > 0) {
                if (imsi.startsWith("46000") || imsi.startsWith("46002")) {
                    return "中国移动";
                } else if (imsi.startsWith("46001")) {
                	return "中国联通";
                } else if (imsi.startsWith("46003")) {
                	return "中国电信";
                } else {
                	return telephonyManager.getSimOperatorName();
                }
            }
		}
		return "";
	}
	
	/**
	 * 获取设备MAC地址
	 * @param context
	 * @return
	 */
	static String getDeviceMac(Context context){
	    //获取WiFi Mac地址
        WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo info = wifi.getConnectionInfo();
        String mac = (info == null) ? "" : (info.getMacAddress() == null ? "" : info.getMacAddress()).toLowerCase();
        return mac;
	}
	
	static class NetspeedData {
        private JSONArray jsonArray;
        private List<Integer> idList;
        public JSONArray getJsonArray() {
            return jsonArray;
        }

        public void setJsonArray(JSONArray jsonArray) {
            this.jsonArray = jsonArray;
        }

        public List<Integer> getIdList() {
            return idList;
        }

        public void setIdList(List<Integer> idList) {
            this.idList = idList;
        }
    }
}
