package ai.pai.client.services;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.text.TextUtils;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.android.common.executors.ThreadExecutor;
import com.android.common.utils.LogHelper;
import com.android.common.utils.TimeUtils;

import org.json.JSONObject;

import java.util.HashMap;

import ai.pai.client.db.Preferences;
import ai.pai.client.utils.HttpPostTask;
import ai.pai.client.utils.UrlContainer;


public class MyLocationService extends Service implements Handler.Callback{

    private AMapLocationClient locationClient = null;
    private AMapLocationClientOption locationOption = new AMapLocationClientOption();

    public static final int COMMAND_START_LOCATION = 9801;
    public static final int COMMAND_DESTROY_LOCATION = 9803;

    private double lastLat;
    private double lastLon;
    private double repeatTime;

    private static final int FETCH_GATHER_INFO_PERIOD = 20*60*1000;
    private static final int LOCATION_MAX_PERIOD = 10*60*1000;
    private static final int LOCATION_MIN_PERIOD = 60*1000;
    private static final int LOCATION_PERIOD_CHANGE_DEADLINE = 15*60*1000;
    private static final int MSG_FETCH_TOUR_INFO = 4567;
    private static final int MSG_START_LOCATION = 4568;

    private Handler mHandler;

    private HttpPostTask fetchTourInfoTask;

    @Override
    public void onCreate() {
        super.onCreate();
        mHandler = new Handler(this);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if(intent==null){
            return super.onStartCommand(intent,flags,startId);
        }
        Bundle bundle= intent.getExtras();
        if(bundle==null){
            return super.onStartCommand(intent, flags, startId);
        }
        int command = bundle.getInt("command",0);
        initLocation();
        initGatherInfo();
        switch (command) {
            case COMMAND_START_LOCATION:
                startLocation();
                break;
            case COMMAND_DESTROY_LOCATION:
                destroyLocation();
                break;
        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        destroyLocation();
    }


    private void initLocation(){
        if(locationClient!=null){
            return;
        }
        locationClient = new AMapLocationClient(getApplicationContext());
        locationClient.setLocationOption(getDefaultOption());
        locationClient.setLocationListener(locationListener);
    }

    private void initGatherInfo(){
        if(!Preferences.getInstance(this).isTourMode()&&Preferences.getInstance(this).getTourEndTime()<System.currentTimeMillis()){
            return;
        }
        long gatherTime = Preferences.getInstance(this).getGatherTime();
        if(gatherTime<System.currentTimeMillis()){
            mHandler.sendEmptyMessageDelayed(MSG_FETCH_TOUR_INFO,60000);
        }
    }

    private void fetchTourInfo(){
        mHandler.sendEmptyMessageDelayed(MSG_FETCH_TOUR_INFO,FETCH_GATHER_INFO_PERIOD);
        if(!Preferences.getInstance(this).isTourMode()&&Preferences.getInstance(this).getTourEndTime()<System.currentTimeMillis()){
            return;
        }
        long gatherTime = Preferences.getInstance(this).getGatherTime();
        if(gatherTime>System.currentTimeMillis()){
            return;
        }
        if(fetchTourInfoTask!=null && fetchTourInfoTask.getStatus()== AsyncTask.Status.RUNNING){
            return;
        }
        HashMap<String,String> params = new HashMap<String,String>();
        String userId = Preferences.getInstance(this).getUserId();
        if(userId.length()==0){
            return;
        }
        params.put("user_id",userId);

        fetchTourInfoTask = new HttpPostTask(this,params) {


            @Override
            protected boolean parseResponse(Context context, String response) {
                try{
                    JSONObject json = new JSONObject(response);
                    int status = json.getInt("status");
                    if(status == 200){
                        JSONObject data = json.getJSONObject("data");
                        String groupId = data.getString("group_id");
                        if(!TextUtils.isEmpty(groupId)){
                            Preferences.getInstance(context).setTourMode(true);
                            JSONObject group = data.getJSONObject("group");
                            String phone = group.getString("phone");
                            Preferences.getInstance(context).setTourGuidePhone(phone);
                            String gatherTimeStr = group.getString("gather_at");
                            Preferences.getInstance(context).setGatherTime(TimeUtils.getStandardTimeInMiliSec(gatherTimeStr));
                            String endTimeStr = group.getString("ended_at");
                            Preferences.getInstance(context).setTourEndTime(TimeUtils.getStandardTimeInMiliSec(endTimeStr));
                            if(group.has("gather_location")){
                                String location = group.getString("gather_location");
                                Preferences.getInstance(context).setTourGatherLocation(location);
                            }
                        }
                    }else{
                        Preferences.getInstance(context).setTourGatherLocation("");
                        Preferences.getInstance(context).setTourMode(false);
                        Preferences.getInstance(context).setTourGuidePhone("");
                        Preferences.getInstance(context).setGatherTime(0);
                        Preferences.getInstance(context).setTourEndTime(0);
                    }
                    return true;
                }catch (Exception e){
                    e.printStackTrace();
                }
                return false;
            }

            @Override
            protected void onPostSuccess(Context context) {
                super.onPostSuccess(context);
                if(mHandler!=null){
                    mHandler.sendEmptyMessage(MSG_START_LOCATION);
                }
            }
        };
        fetchTourInfoTask.executeOnExecutor(ThreadExecutor.getInstance().getExecutor(), UrlContainer.TOUR_INFO_URL);

    }
    private AMapLocationClientOption getDefaultOption(){
        AMapLocationClientOption mOption = new AMapLocationClientOption();
        mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选，设置定位模式，可选的模式有高精度、仅设备、仅网络。默认为高精度模式
        mOption.setGpsFirst(false);//可选，设置是否gps优先，只在高精度模式下有效。默认关闭
        mOption.setHttpTimeOut(30000);//可选，设置网络请求超时时间。默认为30秒。在仅设备模式下无效
        mOption.setInterval(30*1000);//可选，设置定位间隔。默认为30秒
        mOption.setNeedAddress(true);//可选，设置是否返回逆地理地址信息。默认是true
        mOption.setOnceLocation(true);//可选，设置是否单次定位。默认是false
        mOption.setOnceLocationLatest(false);//可选，设置是否等待wifi刷新，默认为false.如果设置为true,会自动变为单次定位，持续定位时不要使用
        AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP);//可选， 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
        mOption.setSensorEnable(false);//可选，设置是否使用传感器。默认是false
        mOption.setWifiScan(true); //可选，设置是否开启wifi扫描。默认为true，如果设置为false会同时停止主动刷新，停止以后完全依赖于系统刷新，定位位置可能存在误差
        return mOption;
    }

    AMapLocationListener locationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation loc) {
            if(loc.getErrorCode()==AMapLocation.ERROR_CODE_FAILURE_LOCATION_PERMISSION){
                Preferences.getInstance(getApplicationContext()).setPermissionGranted(false);
            }
            double lat = loc.getLatitude();
            double lon = loc.getLongitude();
            LogHelper.dfile("czy","经纬度 lat = "+lat+"lon="+lon+" 位置 ="+loc.getAddress());
            reportLocationWhenTourMode(lat,lon);
        }
    };


    private void startLocation(){
        initLocation();
        if(Preferences.getInstance(this).isTourMode()){
            locationClient.setLocationOption(locationOption);
            locationClient.startLocation();
            if(Preferences.getInstance(this).getGatherTime()> System.currentTimeMillis()){
                mHandler.sendEmptyMessageDelayed(MSG_START_LOCATION,Preferences.getInstance(this)
                        .getGatherTime()-System.currentTimeMillis()>LOCATION_PERIOD_CHANGE_DEADLINE ? LOCATION_MAX_PERIOD:LOCATION_MIN_PERIOD);
            }
        }
    }


    private void destroyLocation(){
        if (null != locationClient) {
            locationClient.stopLocation();
            locationClient.onDestroy();
            locationClient = null;
            locationOption = null;
        }
        mHandler.removeCallbacksAndMessages(null);
    }

private void reportLocationWhenTourMode(double lat, double lon){
    if(locationClient!=null){
        locationClient.stopLocation();
    }
    if(lat == lastLat && lon ==lastLon && repeatTime<5){
        repeatTime++;
        return;
    }
    repeatTime = 0;
    lastLat = lat;
    lastLon = lon;
    HashMap<String,String> params = new HashMap<String,String>();
    String userId = Preferences.getInstance(this).getUserId();
    if(userId.length()==0){
        return;
    }
    params.put("user_id",userId);
    params.put("lon",String.valueOf(lon));
    params.put("lat",String.valueOf(lat));
    new HttpPostTask(this,params).executeOnExecutor(ThreadExecutor.getInstance().getExecutor(), UrlContainer.GEO_LOCATION_URL);
}

    @Override
    public boolean handleMessage(Message msg) {
        if(msg.what == MSG_FETCH_TOUR_INFO){
            fetchTourInfo();
            return true;
        }else if(msg.what == MSG_START_LOCATION){
            startLocation();
            return true;
        }
        return false;
    }
}
