package com.imofan.android.basic.update;
import android.app.AlertDialog;
import android.app.Activity;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import com.imofan.android.basic.notification.MFPreferencesUtils;

/**
 * 应用自动更新服务类，用于自动获取应用最新版本并进行更新
 */
public class MFUpdateService extends Service {
	
	private static boolean isDefaultUpdateDialog = true;
    
    //更新接口
    private static String CHECKURL;
    
    //下载状态
    private final static int DOWNLOAD_COMPLETE = 0;
    private final static int DOWNLOAD_URL_ERROR = 1;
    private final static int DOWNLOAD_FAIL = 2;
    private final static int CREATE_FILE_FAIL = 3;
    
    //App信息
    private static MFAPPInfo mfappInfo;
    
    //更新文件和更新跳转
    private String updateNotificationTitle;
    public static File updateFile;
    private static PendingIntent updatePendingIntent;
    private static int updateTotalSize = 0;
    private NotificationManager updateNotificationManager;
    private NotificationCompat.Builder builderNotification;
    
    //布局资源
    private static int iconID = 0;
    private static int appNameID=0; 
//    private static int layoutID;
//    private static int textViewID;
//    private static int blockViewID;
//    private static int processbarViewID;
//    private static int notificationBarIconViewID;
//    private static int notificationBarAppNameViewID;
    
    /**
     * 下载完成的Apk临时存放目录
     */
    public static File internalFileDir;
    
    //更新的信息
    public static int updateApkVersionCode;
    private static String updateApkDownloadUrl;
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    @Override
    public void onCreate() {
        mfappInfo=MFUpdateUtils.getVersionInfo(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //接受传递参数
        iconID = intent.getIntExtra("iconID", 0);
        appNameID = intent.getIntExtra("appNameID", 0);
        updateApkVersionCode = intent.getIntExtra("versionCode", 0);
        updateApkDownloadUrl = intent.getStringExtra("downloadUrl");
        
        //创建下载APK存储目录
        createAPKStorageFile();
        
        Intent updateCompletingIntent = new Intent();
        updateCompletingIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        updateCompletingIntent.setClass(getApplication().getApplicationContext(),
                MFUpdateService.class);

        updatePendingIntent = PendingIntent.getActivity(MFUpdateService.this, appNameID,
                updateCompletingIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        
        this.updateNotificationTitle = getResources().getString(appNameID);
        
        updateNotificationManager = (NotificationManager)getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
        
        builderNotification = new NotificationCompat.Builder( getApplicationContext());
        builderNotification.setSmallIcon(iconID)
				        .setContentTitle(updateNotificationTitle)
				        .setContentIntent(updatePendingIntent)
				        .setAutoCancel(true)
				        .setTicker("开始更新") // 设置状态栏提示信息
				        .setDefaults(Notification.DEFAULT_SOUND)  // 设置声音
				        .setProgress(100, 0, false)
				        .setContentText("下载进度")
				        .build();
        updateNotificationManager.notify(iconID, builderNotification.build());
        
        new Thread(updateRunnable).start();
        return super.onStartCommand(intent, flags, startId);
    }

        
    /**
     * 用于检查是否有新版本的app可以更新
     * @param activity 当前activity对象
     * @param updateListener 更新情况监听器
     * @param showUpdateDialog 是否显示更新提示框
     * @param wifiOnly 是否仅在WIFI环境下进行更新
     */
    public static void check(final Activity activity, final MFUpdateListener updateListener ,final boolean showUpdateDialog, final boolean wifiOnly) {
        //获取当前应用版本信息
        mfappInfo = MFUpdateUtils.getVersionInfo(activity);
        CHECKURL=getCheckUrl(activity.getApplicationContext(),mfappInfo);
        new Thread() {
            public void run() {
                //WIFI下更新
                if(wifiOnly && MFNetworkUtils.STATE_WIFI == MFNetworkUtils.getNetworkState(activity)){
                    MFUpdateAPKInfo  mfInfo = MFUpdateUtils.checkNewVersion(CHECKURL);
                    if(null!=mfInfo && mfInfo.getVersionCode() > mfappInfo.getVersionCode()) {
                        if(showUpdateDialog){
                            activity.runOnUiThread(new UpdateThread(activity,mfInfo,updateListener));
                        }else{
                            updateListener.onDetectedNewVersion(activity, mfInfo.getVersionCode(), mfInfo.getVersionName(), 
                                    mfInfo.getDescription(), mfInfo.getApkPath());
                        }
                        
                    }else if(null!=mfInfo && mfInfo.getVersionCode() <= mfappInfo.getVersionCode()){
                        updateListener.onDetectedNothing(activity);
                    }else{
                        updateListener.onFailed(activity);
                    }
                //WIFI关闭时    
                }else if(wifiOnly && MFNetworkUtils.WIFI_OFF == MFNetworkUtils.getWifiIsEnabled(activity)){
                    updateListener.onWifiOff(activity);
                    
                //如果网络可以用，不论是否处于WIFI环境均进行检查    
                }else if(!wifiOnly){
                    MFUpdateAPKInfo  mfInfo = MFUpdateUtils.checkNewVersion(CHECKURL);
                    if(null!=mfInfo && mfInfo.getVersionCode() > mfappInfo.getVersionCode()) {
                        if(showUpdateDialog){
                            activity.runOnUiThread(new UpdateThread(activity,mfInfo,updateListener));
                        }else{
                            updateListener.onDetectedNewVersion(activity, mfInfo.getVersionCode(), mfInfo.getVersionName(), 
                                    mfInfo.getDescription(), mfInfo.getApkPath());
                        }
                    }else if(null!=mfInfo && mfInfo.getVersionCode() <= mfappInfo.getVersionCode()){
                        updateListener.onDetectedNothing(activity);
                    }else{
                        updateListener.onFailed(activity);
                    }
                }
            }
        }.start();
    }
    
    
    /**
     * 用于检查是否有新版本的app可以更新，不论是否处于WIFI环境均进行检查
     * @param updateListener 更新情况监听器
     * @param showUpdateDialog 是否显示更新提示框
     */
    public static void check(Activity activity,MFUpdateListener updateListener,final boolean showUpdateDialog) {
        check(activity,updateListener,showUpdateDialog,false);
    }
    

    /**
     * 全自动更新，当发现新版本时自动弹出更新提示对话框并进行后续更新
     * @param activity 用于显示更新提示对话框的Activity
     * @param appNameID 应用名称
     * @param notificationIconId 通知栏显示图标
     * @param wifiOnly 是否仅在WIFI环境下进行更新
     */
    public static void autoUpdate(final Activity activity,final int appNameID,
            final int notificationIconId, final boolean wifiOnly) {
        mfappInfo = MFUpdateUtils.getVersionInfo(activity.getApplicationContext());
    	CHECKURL=getCheckUrl(activity.getApplicationContext(),mfappInfo);
    	
    	
    	new Thread() {
    		public void run() {
    			//WIFI环境更新
    			if(wifiOnly && MFNetworkUtils.STATE_WIFI == MFNetworkUtils.getNetworkState(activity)){
    				MFUpdateAPKInfo  mfInfo = MFUpdateUtils.checkNewVersion(CHECKURL);
    				boolean isIgnore = isIgnoreVersion(activity, mfInfo);
    				if(!isIgnore && null!=mfInfo && mfInfo.getVersionCode() > mfappInfo.getVersionCode()) {
    					activity.runOnUiThread(new UpdateThread(activity,mfInfo,appNameID,
    							notificationIconId));
    				}
    				//任何网络都更新
    			}else if(!wifiOnly && MFNetworkUtils.isNetworkAvailable(activity)){
    				MFUpdateAPKInfo  mfInfo = MFUpdateUtils.checkNewVersion(CHECKURL);
    				boolean isIgnore = isIgnoreVersion(activity, mfInfo);
    				if(!isIgnore && null!=mfInfo && mfInfo.getVersionCode() > mfappInfo.getVersionCode()) {
    					activity.runOnUiThread(new UpdateThread(activity,mfInfo,appNameID,
    							notificationIconId));
    				}
    			}
    		}
    	}.start();
    }
    
    
    /**
     * 全自动更新，当发现新版本时自动弹出更新提示对话框并进行后续更新，不论是否处于WIFI环境均进行更新
     * @param activity 用于显示更新提示对话框的context对象
     * @param appNameID 应用名称资源ID
     * @param notificationIconId 通知栏显示图标资源ID
     */
    public static void autoUpdate(Activity activity,int appNameID,int notificationIconId) {
        autoUpdate(activity,appNameID,notificationIconId , false);
    }
    
    /**
     * 检查是否为忽略升级
     * @param mfappInfo
     * @return
     */
    private static boolean isIgnoreVersion(Activity activity,MFUpdateAPKInfo mfappInfo){
    	//忽略升级的版本
    	int ignoreVersion = MFPreferencesUtils.getPreference(activity, "ignoreUpdate", "version", 0);
    	//当前最新版本
    	if(mfappInfo!=null){
    		int currentVersion = mfappInfo.getVersionCode();
    		if(ignoreVersion==currentVersion){
    			return true;
    		}
    	}
    	return false;
    }
    	
    
    /**
     * 获取更新接口
     * @param context 
     * @return
     */
    private static String getCheckUrl(Context context,MFAPPInfo mfappInfo){
        if(null==CHECKURL){
            try {
                String mofangAppKey = (String)context.getPackageManager().getApplicationInfo(
                        context.getPackageName(), PackageManager.GET_META_DATA).metaData.get("MOFANG_APPKEY");
                if(null!=mofangAppKey && !"".equals(mofangAppKey)){
                    CHECKURL = "http://m.imofan.com/online_update/?app_key="+mofangAppKey+"&ver="+mfappInfo.getVersionName();
                }
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        return CHECKURL; 
    }
    
    /**
     * 是否使用默认的升级提示dialog，如果时则不用调用该方法。要自定义则直接使用layout中的
     * updata_dialog_next_layout.xml,里面id和布局不要改变，只动颜色可以
     * @param useDefaultUpdateDialog
     */
    public static void setDefaultUpdateDialog(final boolean useDefaultUpdateDialog){
    	isDefaultUpdateDialog = useDefaultUpdateDialog;
    }
    
    private static class UpdateThread implements Runnable {
        private Activity activity;
        private MFUpdateAPKInfo updateInfo;
        private int notificationIconResId;
        private int appNameID;
        private MFUpdateListener mfUpdateListener;
        
        public UpdateThread(Activity activity,MFUpdateAPKInfo mfUpdateInfo,int appNameID,
                            int notificationIconResId) {
            this.activity = activity;
            this.updateInfo = mfUpdateInfo;
            this.appNameID = appNameID;
            this.notificationIconResId = notificationIconResId;
        }
        
        public UpdateThread(Activity activity,MFUpdateAPKInfo mfUpdateInfo,MFUpdateListener listener) {
            this.activity = activity;
            this.updateInfo = mfUpdateInfo;
            this.mfUpdateListener = listener;
        }

        public void run() {
        	if (isDefaultUpdateDialog) {
        		AlertDialog.Builder alertBuilder = new AlertDialog.Builder(activity);
                alertBuilder.setTitle("软件升级")
                    .setPositiveButton("更新", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            if(mfUpdateListener!=null){
                                mfUpdateListener.onPerformUpdate(activity, updateInfo.getVersionCode(), updateInfo.getVersionName(), updateInfo.getDescription(),updateInfo.getApkPath());
                            }else{
                                //开启下载服务
                                Intent serviceIntent = new Intent(activity, MFUpdateService.class);
                                serviceIntent.putExtra("iconID", notificationIconResId);//图标
                                serviceIntent.putExtra("appNameID", appNameID);//应用名称
                                serviceIntent.putExtra("downloadUrl", updateInfo.getApkPath());
                                serviceIntent.putExtra("versionCode", updateInfo.getVersionCode());
                                activity.startService(serviceIntent);
                            }
                        }
                    }).setNeutralButton("忽略此版本",  new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                        	//将忽略升级的版本进行存储
                        	MFPreferencesUtils.setPreferences(activity, "ignoreUpdate", "version", updateInfo.getVersionCode());
                            dialog.cancel();
                        }
                    })
                    .setNegativeButton("下次吧", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                        }
                    }).setView(MFUpdateUtils.createUpdateDialog(activity,updateInfo));
                alertBuilder.create().show();
			}else{
				final View v = this.activity.getLayoutInflater().inflate(MFUpdateUtils.getIdByReflection(activity, "layout", "updata_dialog_layout"), null);
	            final Dialog dialog = new Dialog(this.activity);
	            View.OnClickListener onClickListener = new View.OnClickListener(){

					@Override
					public void onClick(View v) {
						if (v != null) {
		                  int id = v.getId();
		                  if (id == MFUpdateUtils.getIdByReflection(activity, "id", "updata_dialog_next_layout")) {        //下次
		                	  dialog.cancel();
		                  } else if (id == MFUpdateUtils.getIdByReflection(activity, "id", "updata_dialog_ignore_layout")){//忽略
		                	  MFPreferencesUtils.setPreferences(activity, "ignoreUpdate", "version", updateInfo.getVersionCode());
		                	  dialog.cancel();
		                  } else if (id == MFUpdateUtils.getIdByReflection(activity, "id", "updata_dialog_sure_layout")) {
		                	  if(mfUpdateListener!=null){
			                      Log.i("xjzhao", "mfUpdateListener");
			                      mfUpdateListener.onPerformUpdate(activity, updateInfo.getVersionCode(), updateInfo.getVersionName(), updateInfo.getDescription(),updateInfo.getApkPath());
		                    } else {
		                    	Log.i("xjzhao", "开启下载服务");

		                        //开启下载服务
		                        Intent serviceIntent = new Intent(activity, MFUpdateService.class);
		                        serviceIntent.putExtra("iconID", notificationIconResId);//图标
		                        serviceIntent.putExtra("appNameID", appNameID);//应用名称
		                        serviceIntent.putExtra("downloadUrl", updateInfo.getApkPath());
		                        serviceIntent.putExtra("versionCode", updateInfo.getVersionCode());
		                        activity.startService(serviceIntent);
		                    }
		                    dialog.cancel();
		                  }
		                }
					}
					
	            };
	            dialog.requestWindowFeature(1);
	            dialog.setContentView(v);
	            LinearLayout next = (LinearLayout)v.findViewById(MFUpdateUtils.getIdByReflection(this.activity, "id", "updata_dialog_next_layout"));
	            LinearLayout ignore = (LinearLayout)v.findViewById(MFUpdateUtils.getIdByReflection(this.activity, "id", "updata_dialog_ignore_layout"));
	            LinearLayout sure = (LinearLayout)v.findViewById(MFUpdateUtils.getIdByReflection(this.activity, "id", "updata_dialog_sure_layout"));
	            TextView text = (TextView)v.findViewById(MFUpdateUtils.getIdByReflection(this.activity, "id", "updata_dialog_text"));
	            text.setText(MFUpdateUtils.replaceBr(this.updateInfo.getDescription()));
	            next.setOnClickListener(onClickListener);
	            ignore.setOnClickListener(onClickListener);
	            sure.setOnClickListener(onClickListener);
	            dialog.show();
			}
            
        	
        	
        	
          }
    }
    
    
    private Handler updateHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what){
                case DOWNLOAD_COMPLETE:
                    //files目录下文件安装需要权限，赋予777权限
                    String cmd = "chmod 777 " +updateFile.getPath();
                    try {
                        Runtime.getRuntime().exec(cmd);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    
                    //设置点击跳转Activity
                    Uri uri = Uri.fromFile(updateFile);
                    Intent updateCompleteIntent = new Intent(Intent.ACTION_VIEW);
                    updateCompleteIntent.setDataAndType(
                            uri, "application/vnd.android.package-archive");

                    updatePendingIntent = PendingIntent.getActivity(
                            MFUpdateService.this, appNameID, updateCompleteIntent,
                            PendingIntent.FLAG_UPDATE_CURRENT);
                    
                    builderNotification.setSmallIcon(iconID)
				        .setContentTitle(updateNotificationTitle)
				        .setContentIntent(updatePendingIntent)
				        .setAutoCancel(true)
				        .setTicker("更新完成") // 设置状态栏提示信息
				        .setDefaults(Notification.DEFAULT_SOUND)  // 设置使用所有默认值（声音、震动、闪屏等）
				        .setProgress(0,0,false)
				        .setContentText("更新完成,点击安装")
				        .build();
                    updateNotificationManager.notify(iconID, builderNotification.build());
                    break;
                case DOWNLOAD_URL_ERROR:
                    //下载地址为空
                	onFailNotification();
                    break;
                case CREATE_FILE_FAIL:
                    //创建文件失败
                	onFailNotification();
                    break;
                case DOWNLOAD_FAIL:
                	//其他错误
                	onFailNotification();
                    break;
                default:
            }
            stopSelf();
            super.handleMessage(msg);
        }        
    };
    
    
    private void onFailNotification(){
    	 builderNotification.setSmallIcon(iconID)
	        .setContentTitle("更新失败，请重新下载")
	        .setContentIntent(updatePendingIntent)
	        .setAutoCancel(true)
	        .setTicker("更新失败") // 设置状态栏提示信息
	        .setDefaults(Notification.DEFAULT_SOUND)  // 设置使用所有默认值（声音、震动、闪屏等）
	        .setProgress(100, 0, false)
	        .setContentText("下载进度")
	        .build();
    	 updateNotificationManager.notify(iconID, builderNotification.build());
    }
    
    
    /**
     *  更新下载线程
     * @author user
     *
     */
    private Runnable updateRunnable = new Runnable(){
        Message message = updateHandler.obtainMessage();
        public void run() {
            try{   
                message.what = DOWNLOAD_COMPLETE;
                if(!updateFile.exists()){
                    updateFile.createNewFile();
                }else{
                    try{
                        PackageManager pManager = MFUpdateService.this.getPackageManager();
                        PackageInfo pInfo = pManager.getPackageArchiveInfo(
                                updateFile.getPath(), PackageManager.GET_ACTIVITIES);
                        
                        //如果已经下载，检查下载文件的版本
                        if(pInfo != null){
                            if(updateApkVersionCode > 0  && updateApkVersionCode == pInfo.versionCode){
                                updateHandler.sendMessage(message);
                                return;
                            }else{
                                //如果是老版本的，删除并准备重新下载
                                updateFile.delete();
                                updateFile.createNewFile();
                            }
                        }
                    }catch(Exception ex){
                        ex.printStackTrace();
                    }
                }
               
                long size = 0;
                //判断服务器下载地址
                if(updateApkDownloadUrl == null || "".equals(updateApkDownloadUrl)){
                    message.what = DOWNLOAD_URL_ERROR;
                }else{
                    size = downloadUpdateFile(updateApkDownloadUrl, updateFile, true);
                    if(size == 0){ 
                        message.what = DOWNLOAD_FAIL;
                    }
                }
                updateHandler.sendMessage(message);
            }catch(IOException e){
                e.printStackTrace();
                message.what = DOWNLOAD_FAIL;
                updateHandler.sendMessage(message);
            }catch(Exception ex){
                ex.printStackTrace();
                message.what = DOWNLOAD_FAIL;
                updateHandler.sendMessage(message);
            }
        }
    };
    
    
    /**
     * 下载最新APK
     * @param urlStr 下载apk地址
     * @param dest    APK存放文件
     * @param append 是否断点续传
     * @return  下载文件大小
     * @throws Exception
     */
    private long downloadUpdateFile(String urlStr, File dest, boolean append) throws Exception {
    	
        int downloadCount = 0;
        int currentSize = 0;
        long totalSize = 0;
        if(append) {
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(dest);
                currentSize = fis.available();
            } catch(IOException ex) {
                ex.printStackTrace();
            } finally {
                if(fis != null) {
                    fis.close();
                }
            }
        }
        HttpURLConnection httpConnection = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            URL url = new URL(urlStr);
            httpConnection = (HttpURLConnection)url.openConnection();
            httpConnection.setRequestProperty("User-Agent", "PacificHttpClient");
            if(currentSize > 0) {
                httpConnection.setRequestProperty("RANGE", "bytes=" + currentSize + "-");
            }
            httpConnection.setConnectTimeout(10000);
            httpConnection.setReadTimeout(20000);
            updateTotalSize = httpConnection.getContentLength();
            if (httpConnection.getResponseCode() == 404) {
                throw new Exception("Cannot find remote file:" + urlStr);
            }
            is = httpConnection.getInputStream();
            fos = new FileOutputStream(dest, append);
            byte buffer[] = new byte[4096];
            int readsize = 0;
            
            builderNotification.setSmallIcon(iconID)
		        .setContentTitle(updateNotificationTitle)
		        .setContentIntent(updatePendingIntent)
		        .setAutoCancel(true)
		        .setTicker("正在更新") // 设置状态栏提示信息
		        .setDefaults(0)  // 设置使用所有默认值（声音、震动、闪屏等）
		        .setContentText("下载进度")
		        .build();
            while((readsize = is.read(buffer)) > 0){
                fos.write(buffer, 0, readsize);
                totalSize += readsize;
                if((downloadCount == 0)||(int) (totalSize*100/updateTotalSize)-8>downloadCount){ 
                    downloadCount += 8;
                    builderNotification.setProgress(100, downloadCount, false);
                    updateNotificationManager.notify(iconID, builderNotification.build());
                }
            }
        }finally {
            if(httpConnection != null) {
                httpConnection.disconnect();
            }
            if(is != null) {
                is.close();
            }
            if(fos != null) {
                fos.close();
            }
        }
        return totalSize;
    }
    
    
    /**
     * 创建更新APK的存储文件
     * @param internalFileDir 存储apk的目录
     * @param apkVersionCode 应用的版本号
     * 
     */
    private void createAPKStorageFile(){
        internalFileDir = getDir("update", MODE_PRIVATE);
        if(null!=internalFileDir && internalFileDir.isDirectory()){
            File[] files = internalFileDir.listFiles();
            if(null!=files){
                for(int i=0;i<files.length;i++){
                    MFUpdateUtils.delete(files[i]);
                }
            }
        }
        updateFile = new File(internalFileDir.getAbsolutePath(),File.separator+mfappInfo.getPackageName()+"_"+updateApkVersionCode+".apk");
    }
}
