package com.imofan.android.basic.feedback;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import com.imofan.android.basic.MFStatInfo;
import com.imofan.android.basic.Mofang;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;



/**
 * 用于提供用户反馈功能的服务类
 */
public class MFFeedbackService {
	
	private final static String ACCEPT_ENCODING = "gzip, deflate";
	
	//超时时间
    private static int CONNECT_TIMEOUT = 20;
    private static int DATA_TIMEOUT = 40;
    
	//URL
	private static String FEEDBACK_URL = "http://m.imofan.com/feedbacks/?app_key=";
	private static String UUID_URL = "http://m.imofan.com/uuid.jsp";
	
	//提交
	private static final int SUBMIT_FAILED = -1;
	
	//本地SharedPreferences存储文件
	private static final String SP_FILE_NAME = "mffeedbacks";
	
    /**
     * 提交用户反馈
     * @param activity Activity对象
     * @param feedbackSubmitListener 用于监听提交情况的监听器
     * @param feedback 用户反馈类对象
     */
    public static void submit(Activity activity,MFFeedback feedback,MFFeedbackSubmitListener feedbackSubmitListener) {
    	
    	final Activity activity1 = activity;
    	final MFFeedback feedBack1 = feedback;
    	final MFFeedbackSubmitListener feedbackSubmitListener1 = feedbackSubmitListener;
    	
    	new Thread(new Runnable() {
			public void run() {
				if(null==activity1 || null==feedBack1 ||feedBack1.getFeedback().length()>500
				    	   ||null==feedbackSubmitListener1){
				    		feedbackSubmitListener1.onSubmitFailed();
				    		return;
				    	}
				    	
				
				    	String backJson = null;
				    	Map<String,String> maps = null;
				    	backJson = getSubmitResponseWithPost(activity1,feedBack1);

						if("".equals(backJson) || null==backJson){
							feedbackSubmitListener1.onSubmitFailed();
							return;
						}
						
						maps = MFFeedbackService.getSubmitBackInfo(backJson);
						if(null==maps){
							feedbackSubmitListener1.onSubmitFailed();
							return;
						}
						
						if(Integer.parseInt(maps.get("status")) == SUBMIT_FAILED){
							feedbackSubmitListener1.onSubmitFailed();
							return;
						}
						
						update(activity1,new MFFeedbackReplyListener() {
							@Override
							public void onDetectedNothing() {
							}
							@Override
							public void onDetectedNewReplies(List<MFFeedback> feedbacks) {
							}
						});
						feedbackSubmitListener1.onSubmitSucceeded(feedBack1);
			}
		}).start();
    	
    }
    
    /**
     * 获取本地SharedPreferences里所有的"反馈及回复"信息
     * @param activity
     */
    public static List<MFFeedback> getLocalAllReply(Activity activity){
    	List<MFFeedback> list = new ArrayList<MFFeedback>();
    	SharedPreferences preferences = activity.getSharedPreferences(SP_FILE_NAME,activity.MODE_PRIVATE);
    	String json = preferences.getString("json", null);
    	
    	if(null != json){
    		try {
				JSONObject jsonObj = new JSONObject(json);
				JSONArray jsonArray = jsonObj.getJSONArray("feedbacks");
				for(int i=0;i<jsonArray.length();i++){
					MFFeedback fd = new MFFeedback(jsonArray.getJSONObject(i).getString("feedback"));
					fd.setUserType(jsonArray.getJSONObject(i).getInt("by"));
					fd.setTimestamp(jsonArray.getJSONObject(i).getString("timestamp"));
					list.add(fd);
				}
			} catch (JSONException e) {
				printErr(e);
				return list;
			}
    	}
    	
    	return list;
    }
    
    
    /**
     * 获取新消息内容:
     * 更新本地SharedPreferences里的"反馈及回复"信息,若发现更新,则会将更新的内容追加至本地SharedPreferences.
     * @param activity				Activity
     * @param feedbackReplyListener	MFFeedbackReplyListener
     */
    public static void update(Activity activity,MFFeedbackReplyListener feedbackReplyListener){
    	
    	final Activity activity1 = activity;
    	final MFFeedbackReplyListener feedbackReplyListener1 = feedbackReplyListener;
    	
    	new Thread(new Runnable() {	
			@Override
			public void run() {
				if(null==activity1 || null==feedbackReplyListener1){
		    		feedbackReplyListener1.onDetectedNothing();
		    		return;
		    	}
		    	
		    	SharedPreferences preferences = activity1.getSharedPreferences(SP_FILE_NAME,activity1.MODE_PRIVATE);
		    	String timestamp = preferences.getString("timestamp", "0");
		    		
		    	String backJson = getFbRspWithGet(activity1,timestamp);
		    	if("".equals(backJson) || null==backJson){
		    		feedbackReplyListener1.onDetectedNothing();
		    		return;
		    	}
		    	List<MFFeedback> list = getUpdateBackInfo(backJson);
		    	if(null == list){
		    		feedbackReplyListener1.onDetectedNothing();
		    		return;
		    	}
		    	//System.out.println("backJson:"+backJson);
		    	saveReply(activity1, backJson);
		    	feedbackReplyListener1.onDetectedNewReplies(list);
			}
		}).start();
    }

    /**
     * 获取新消息条目数
     * @return
     */
   public static void getNewMsgNum(Activity activity,MFFeedbackReplyListener feedbackReplyListener){
       final Activity activity1 = activity;
       final MFFeedbackReplyListener feedbackReplyListener1 = feedbackReplyListener;

       new Thread(new Runnable() {
           @Override
           public void run() {
               if(null==activity1 || null==feedbackReplyListener1){
                   feedbackReplyListener1.onDetectedNothing();
                   return;
               }

               SharedPreferences preferences = activity1.getSharedPreferences(SP_FILE_NAME,activity1.MODE_PRIVATE);
               String timestamp = preferences.getString("timestamp", "0");

               String backJson = getFbRspWithGet(activity1,timestamp);
               if("".equals(backJson) || null==backJson){
                   feedbackReplyListener1.onDetectedNothing();
                   return;
               }
               List<MFFeedback> list = getUpdateBackInfo(backJson);
               if(null==list){
                   feedbackReplyListener1.onDetectedNothing();
                   return;
               }
               feedbackReplyListener1.onDetectedNewReplies(list);
           }
       }).start();
   }
    
    /**
     * 解析JSON
     * @param json 提交意见反馈内容后,服务器响应的JSON格式数据
     * @return	   JSON数据键值对
     */
    private static Map<String,String> getSubmitBackInfo(String json){
    	
    	Map<String,String> maps = new HashMap<String, String>();
    	
    	try {
			JSONObject jsonObj = new JSONObject(json);
			maps.put("status", jsonObj.getString("status"));
			maps.put("desc", jsonObj.getString("desc"));
			maps.put("at", jsonObj.getString("at"));
		} catch (JSONException e) {
			printErr(e);
			return null;
		}
		
		if(maps.isEmpty())
			maps = null;
    	return maps;
    }
    
    /**
     * 解析JSON
     * @param json 检测对指定反馈信息的回复状态,服务器响应的JSON格式数据
     * @return	   JSON数据键值对
     */
    private static List<MFFeedback> getUpdateBackInfo(String json){
    	
    	List<MFFeedback> list = new ArrayList<MFFeedback>();
    	
    	try {
			JSONObject jsonObj = new JSONObject(json);
			JSONArray jsonArray = jsonObj.getJSONArray("feedbacks");
			for(int i=0;i<jsonArray.length();i++){
				JSONObject json1 = jsonArray.getJSONObject(i); 
				MFFeedback fb = new MFFeedback(json1.getString("text"));
				fb.setUserType(json1.getInt("by"));
				fb.setTimestamp(json1.getString("at"));
				list.add(fb);
			}
		} catch (JSONException e) {
			printErr(e);
			return null;
		}
		if(list.isEmpty())
			list = null;
		return list;
    }
    
    /**
     * 存储开发者/用户的"反馈及回复"信息及最后更新时间
     * @param activity
     * @param json
     * @param list
     */
    private static void saveReply(Activity activity,String json){
    	SharedPreferences preferences = activity.getSharedPreferences(SP_FILE_NAME,activity.MODE_PRIVATE);
    	Editor editor  = preferences.edit();
    	
    	List<MFFeedback> list = getUpdateBackInfo(json);
    	editor.putString("timestamp", list.get(list.size()-1).getTimestamp());
    	editor.commit();
    	
    	
    	String localReply = preferences.getString("json", null);
    	if(localReply == null){
    		/*这里有误*/
    		try {
    			JSONObject jsonObj = new JSONObject();
				JSONArray jsonArray = new JSONArray();
				
				for(int i=0;i<list.size();i++){
					JSONObject jo = new JSONObject();
					jo.put("by", list.get(i).getUserType());
					jo.put("feedback", list.get(i).getFeedback());
					jo.put("timestamp", list.get(i).getTimestamp());
					jsonArray.put(jo);
				}
				jsonObj.put("feedbacks", jsonArray);
				editor.putString("json", jsonObj.toString());
	    		editor.commit();
			} catch (JSONException e) {
				printErr(e);
			}
    		
    	}else{//本地已存在意见及回复内容,则追加
			try {
				JSONObject jsonObj = new JSONObject(preferences.getString("json", null));
				JSONArray jsonArray = jsonObj.getJSONArray("feedbacks");
				for(int i=0;i<list.size();i++){
					JSONObject jo = new JSONObject();
					jo.put("by", list.get(i).getUserType());
					jo.put("feedback", list.get(i).getFeedback());
					jo.put("timestamp", list.get(i).getTimestamp());
					jsonArray.put(jo);
				}
				editor.putString("json", jsonObj.toString());
	    		editor.commit();
			} catch (JSONException e) {
				printErr(e);
			}
    	}
    }
    
    private static String getSubmitResponseWithPost(Activity activity,MFFeedback mffeedBack){
    	
    	//防止程序在没有初始化魔方SDK时,直接调用本模块导致无法获取本机参数
    	Mofang.init(activity);
    	
    	String SUBMIT_CONTENT_URL = FEEDBACK_URL;
    	
    	HttpParams param = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(param, CONNECT_TIMEOUT *1000);
        HttpConnectionParams.setSoTimeout(param, DATA_TIMEOUT *1000);
        
    	HttpClient httpClient = new DefaultHttpClient(param);
    	
    	SUBMIT_CONTENT_URL = SUBMIT_CONTENT_URL + Mofang.getAppKey(activity);
    	try {
    		HttpPost post = new HttpPost(SUBMIT_CONTENT_URL);
    		post.setHeader("Accept-Encoding", ACCEPT_ENCODING);
    		
    		List<NameValuePair> params = new ArrayList<NameValuePair>();
    		params.add(new BasicNameValuePair("dev_id", getUUID(activity)));
    		params.add(new BasicNameValuePair("app_ver",MFStatInfo.getString(MFStatInfo.KEY_APP_VERSION, "")));
    		params.add(new BasicNameValuePair("os_ver",MFStatInfo.getString(MFStatInfo.KEY_OS_VERSION, "")));
    		params.add(new BasicNameValuePair("model",MFStatInfo.getString(MFStatInfo.KEY_MODEL, "")));
    		params.add(new BasicNameValuePair("user_info",mffeedBack.getUserInfo()));
    		params.add(new BasicNameValuePair("text",mffeedBack.getFeedback()));
			post.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));
			HttpResponse response = httpClient.execute(post);
			if(response.getStatusLine().getStatusCode() == 200){
				InputStream is = response.getEntity().getContent();
				if(is == null){
					return null;
				}
				Header contentEncoding = response.getFirstHeader("Content-Encoding");
                if(contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
                    is = new GZIPInputStream(is);
                }
				BufferedReader reader = null;
                String line="";
                StringBuffer content = new StringBuffer();
                try {
                    reader = new BufferedReader(new InputStreamReader(is));
                    while((line = reader.readLine()) != null) {
                        content.append(line).append("\r\n");
                    }
                } finally {
                    if(reader != null) {
                        reader.close();
                    }
                    if(is != null) {
                        is.close();
                    }
                }
                return content.toString();
			}
		} catch (UnsupportedEncodingException e) {
			printErr(e);
			return null;
		} catch(IllegalArgumentException e){
			printErr(e);
			return null;
		}catch (ClientProtocolException e) {
			printErr(e);
			return null;
		} catch (IOException e) {
			printErr(e);
			return null;
		}
    	return null;
    }
    
    /**
     * 获取本机UUID
     * @return	UUID
     */
    private static String getUUID(Activity activity){
    	SharedPreferences preferences = activity.getSharedPreferences(SP_FILE_NAME,activity.MODE_PRIVATE);
    	String UUID = preferences.getString("UUID", null);
    	if(UUID != null){
    		return UUID;
    	}else{
    		URL url;
			HttpURLConnection conn;
			try {
				url = new URL(UUID_URL);
			    conn = (HttpURLConnection)url.openConnection();
				conn.setRequestMethod("GET");
				conn.setReadTimeout(5*1000);
				InputStreamReader isr = new InputStreamReader(conn.getInputStream());
				BufferedReader br = new BufferedReader(isr);
				UUID=br.readLine();
				Editor editor  = preferences.edit();
				editor.putString("UUID", UUID);
				editor.commit();
			} catch (MalformedURLException e) {
				printErr(e);
				return null;
			} catch (IOException e) {
				printErr(e);
				return null;
			}
			return UUID;
    	}
    }
    
    /**
     * 获取更新信息的反馈信息
     * @return
     */
    private static String getFbRspWithGet(Activity activity,String ts){
    	
    	//防止程序在没有初始化魔方SDK时,直接调用本模块导致无法获取本机参数
    	Mofang.init(activity);
    	
    	String GET_FEEDBACK_URL = FEEDBACK_URL+Mofang.getAppKey(activity)
    							  +"&dev_id="+getUUID(activity)
    							  +"&ts="+ts;
    	StringBuffer textBuff = new StringBuffer();
    	String line;
    	BufferedReader reader = null;
        try {
        	HttpGet request = new HttpGet(GET_FEEDBACK_URL);
        	request.addHeader("Accept-Encoding", ACCEPT_ENCODING);
        	
        	HttpParams params = new BasicHttpParams();
        	HttpConnectionParams.setConnectionTimeout(params, CONNECT_TIMEOUT *1000);
        	HttpConnectionParams.setSoTimeout(params, DATA_TIMEOUT *1000);
        	HttpClient httpClient = new DefaultHttpClient(params);
        	
            HttpResponse response = httpClient.execute(request);
            if(response.getStatusLine().getStatusCode() == 304) {
                return null;
            }
            InputStream is = response.getEntity().getContent();
            Header contentEncoding = response.getFirstHeader("Content-Encoding");
            if(contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
                is = new GZIPInputStream(is);
            }
            reader = new BufferedReader(new InputStreamReader(is));
            while((line = reader.readLine()) != null) {
                textBuff.append(line).append("\r\n");
            }
        } catch (ClientProtocolException e) {
        	printErr(e);
			return null;
		} catch(IllegalArgumentException e){
			printErr(e);
			return null;
		}catch (IOException e) {
			printErr(e);
			return null;
		} finally {
            if(reader != null) {
                try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
            }
        }
        return textBuff.toString();
    }
    
    private static void printErr(Exception e){
    	if(Mofang.isDebug()){
			e.printStackTrace();
		}
    }
}
