package com.qiyou.mb.android.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.Log;

import com.qiyou.mb.android.QiYouApplication;
import com.qiyou.mb.android.QiYouConstant;
import com.qiyou.mb.android.beans.Track;
import com.qiyou.mb.android.beans.basic.Waypoint_bean;
import com.qiyou.mb.android.utils.Utils;
import com.qiyou.mb.android.utils.enums.TrackStatus;
import com.qiyou.mb.android.utils.enums.wpFlag;
import com.qiyou.mb.android.utils.log.QLog;
//import com.qiyou.mb.android.receivers.ProximIntentReceiver;

public class QNaviSvc extends Service {

	public final static String TAG = "com.qiyou.qnaviSvc";
	public static final String dTAG = "com.qiyou";
//	 public static final String REQEUST_CODE_INTENT_EXTRA="REQEUST_CODE";
//	 public static final String ROADBOOK_INTENT_EXTRA="ROADBOOK";
	
	
//	private HashMap<Integer,PendingIntent> intentMap;
//	private LocationManager locManager  ;
//	private ProximityIntentReceiver proximiReceiver;
	 
	
//	private static final String REQEUST_CODE_INTENT_EXTRA="REQEUST_CODE";
//	private static final String ROADBOOK_INTENT_EXTRA="ROADBOOK";
	private int naviId=0;
	 private long lastCheckNaviPoint=0;
	 private double lastCheckNaviDist=0; //last alert check dist
	 private double lastExistNaviDist=0; //last exist sum dist
	 private boolean isWrongWayAlert;
	 private boolean isFirstWaypoint =false;
	 private long lastTime_avs=0;
	 private float last_avs=0f;
	 private int wrongWayCnt=0;
	 private final String WRONG_WAY="   偏离设定路线。。。 ";
	 private final long WRONG_WAY_MAX_INTERVAL =  300*1000 ;
	 private final long WRONG_WAY_MIN_INTERVAL = 60*1000 ;
	 private final int MIN_TURN_DIST =10; //最小转弯播报距离，小于此距离则直接报 转弯
//	 private final int WRONG_WAY_MAX_DIST=1000;
	 private boolean isNotCheckedin=true;	 
	 private float avDist=50;//average distance for judging wps
	 private float currentDist=0;
	 private float nextDist=0;
	 private float lastDist=0;
	 private int wrongDirectionCnt=0;
	 private final int WRONG_WAY_ALERT_CNT=2;     //cnt passt sine first validation that takes as isWrongWayAlert
	 private final int WRONG_WAY_ALERT_AVDIST_CNT=2; // alert dist limit
	 private final int INT_START_ALERT_CNT=3;     // cnt passed since first validation begin to speach alert msg.
	 private float minDistPlus=0;
//	 private String targetKey="";
//	 private boolean is_targetWb_fired=false;
	 private Vibrator vibrator ;
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
	
	protected QiYouApplication app; 
    @Override
	public void onCreate(){
//    	// // QLog.getLogger().d(dTAG,TAG+"... service naviSvc onCreate.....," );
    	// // QLog.getLogger().d( TAG,TAG+"... service naviSvc onCreate.....," );
    	app = (QiYouApplication) this.getApplication();	 
//         intentMap =new HashMap<Integer,PendingIntent>() ;
       
         
    }
    
    
    @Override
	public int onStartCommand(Intent intent, int flags, int startId){
		// // QLog.getLogger().d( TAG,TAG+"... service NaviSvc onStartCommand.....," );
		handleIntent(intent);
	    // We want this service to continue running until it is explicitly
	    // stopped, so return sticky.
//		return START_NOT_STICKY;		//TODO: checking why can not stop the service.
		return START_STICKY;	
	}
	
   
 private void handleIntent(Intent intent){
    	
    	//to check if the application restart with new instances or not
    	// The check result is, the new application instance created, the original referenced application still exits.
    	
    	//TODO: to find what cause creating new application instances?
    	if(intent==null)return;
    	
    	String key = QiYouConstant.EXTRA_KEY_START_NAVI;
    	
    	
    	if (intent.hasExtra(key)){ 
    		
    		if(app.isNaving && !app.isRestoreNavi)return;
    		 // // QLog.getLogger().dLog(TAG,TAG, "  is Play back?   "+app.playBack );
    		naviId =app.naviTrackId;
    		
    		 if(!app.isRestoreNavi)
    			 sayHello();
    		app.isRestoreNavi=false;
    		initialParameters(); 
    		getChkWps();
    		processNavigation();
//    		 // // QLog.getLogger().dLog(TAG,TAG, " Navigation is done.......................................... ");
//    		 exitNav();
    		return;
    	}
    	  
 }
 
 
 final float sleepFactor=0.5f;		 
 final int turnFactor= 8;//10;//5;
 final int distFactor= 6;//8;
 private long [] vibratorTurnPattern = {100,500,100,500};   // 停止 开启 停止 开启
 private long [] vibratorWrongWayPattern = {100,1000,100,1000};   // 停止 开启 停止 开启
 private boolean mIsFromLast=false;
 private int minSleeptime;
 private int maxSleeptime;

// private HashMap<String,Float> checkWps;
 private HashMap<String, Float[]> checkWps;
	private ArrayList<Waypoint_bean> firedWbs;

 
 private void processNavigation(){
	 
	 // // QLog.getLogger().d( TAG,TAG+"... processNavigation()...." );
	    vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE); 
		new Thread(){
			private ArrayList<Waypoint_bean> alertWbs; 
//			private HashMap<Float,Float> checkWps;
						 Waypoint_bean targetWb;
//			  Location targetLoc;
//			  int distance=0;
//			  int radius=0;
						 
			 
			  int alertDist=0;
			  int sleeptime;;
//			  int minSleeptime;
//			  int maxSleeptime;
			  int maxDist;
//			  int minDist;
//			  float avs=0;
			  int leftDistance=0;
			  boolean isClosing=false;
			  int lastLeft=0;
			  int lastCnt=0;
			  int tringCnt=-5;//numbers of run away from the target
			  int distForSayTurn=0;
//			  long lastLocationTime=0;
			  int speakCnt=0;
//			  boolean isSpeakTurn=false;
//			  float lastDist=0;
			  
			  
			  
			  final String LATERTHEN="然后";//"后" 
			@Override
			public void run() { 
//				isWrongWayAlert=false;
				app.isNaving=true;	
				sleeptime=getinitialSleepTime() ;
			    minSleeptime=sleeptime*5;
			    maxSleeptime =1*60*1000; //最大sleep时间
//			    maxDist=30*sleeptime;//
			    maxDist=1000;//最大1公里
//			    minDist=maxDist/3;  
				Track gpxTrack=null;
		    	alertWbs = new ArrayList<Waypoint_bean>();
		    	firedWbs =new ArrayList<Waypoint_bean>();
		    	if(app.naviTrackId>0){
		    		app.setLastNavId();
//		    		gpxTrack=app.tracks_cached.get(app.naviTrackId);
		    		gpxTrack=app.getTrackCache().get(app.naviTrackId);
		    		if(gpxTrack!=null){
		    			alertWbs.addAll(gpxTrack.getTrackBean().getRoadWps());
		    			 
		    			app.rd=  gpxTrack.getTrackBean().getDistance()/gpxTrack.getTrackBean().getTrkseg().size() >100?100f:1000f;
		    			if(gpxTrack.getTrackBean().getIsCheckedIn()==0){ //骑行最大睡觉时间为2分钟
		    				maxSleeptime = maxSleeptime*2;
		    			}
		    		}
		    		
		    		
		    	}
		    	/*else		    		
		    	for(Integer i:app.getGpxShowingTracks()){
		    		gpxTrack=app.getTrackCache().get(i);
		    		if(gpxTrack!=null)
		    			alertWbs.addAll(gpxTrack.getTrackBean().getRoadWps());  
		    	}*/
		    	
				if(alertWbs.isEmpty())return;
		    	try { 
		    		
 
		    		 
				    if(checkForNewLocation(targetWb )){ 
 
		 				 return;
		 			  }
		    		int minDist=Integer.MAX_VALUE;
		    		int tmpInt=Integer.MAX_VALUE;
		    		int targetIndex = 0;
//		    		Long bfdbTime = System.currentTimeMillis();
		    		int dist;		    		
		    		String LATERTHEN_TURN="";
		    		if(currentDist==0){
			    		for(int i=0;i<alertWbs.size();i++){  //get start target for this loop
			    			targetWb =alertWbs.get(i);
			    			if(targetWb==null)continue;
			    			dist =getLeftDistance(targetWb,alertDist);
			    			if(tmpInt>dist){
			    				tmpInt=dist;
			    				targetIndex=i;
			    			} 
			    		}
		    		}
		    		 else{
		    			 for(int i=0;i<alertWbs.size();i++){  //get start target for this loop
			    			targetWb =alertWbs.get(i);
			    			if(targetWb==null)continue;
			    			dist =(int) targetWb.getSumDist();
//			    			if(tmpInt>dist){
			    			if(dist>currentDist){
//			    				tmpInt=dist;
			    				targetIndex=i;
			    				break;
			    			}
			    		} 
		    		 } 
 
		    		if(targetIndex>0){
		    			firedWbs.addAll(alertWbs.subList(0,targetIndex));
		    			
		    		}
		    		isFirstWaypoint =targetIndex==0;
		    		  // // QLog.getLogger().dLog(TAG,TAG, "Target index is:" +targetIndex);
 				 
//		    		  distForSayTurn =alertDist/10>distForSayTurn?distForSayTurn:alertDist/10;
		    		String targetRoadbook=""; 
		    		String targetTurn="";
		    		String nextGeo =""; 
					Waypoint_bean nextWb;
						
		 		   while(firedWbs.size()<= alertWbs.size()){
		 			   
		 			  // // QLog.getLogger().dLog(TAG,TAG, " firedWbs.size(): " +firedWbs.size());
		 			   
		 			  if(isNaviDone()){
		 				  
		 				 return;
		 			  }
 		 			  speakCnt=0;
		 			  leftDistance=0;
		 			  lastCnt=0; 
		 			  LATERTHEN_TURN="";
		 			  nextDist=0;
		 			  if( wrongWayCnt==0 && isFromLast() && currentDist>0){  //in right way, last target is not right, try to find next right turn
		 				  // // QLog.getLogger().dLog(TAG,TAG, " to find next target, condition is: wrongWayCnt==0 && isFromLast() && currentDist>0"  );
		 				 for(int i=0;i<alertWbs.size();i++){  //get start target for this loop
				    			targetWb =alertWbs.get(i);
				    			if(targetWb==null)continue;
 				    			if(targetWb.getSumDist()>currentDist){
 				    				targetIndex=i;
				    				break;
				    			}
				    		}
 		 				/*targetIndex =targetIndex<alertWbs.size()-1?targetIndex++:targetIndex;*/
  				 
		 				if(targetIndex>0){
		 					firedWbs.clear();
			    			firedWbs.addAll(alertWbs.subList(0,targetIndex));
		 				}
		 				setFromLast(false);
		 				
		 			  }else{
		 				 targetWb =alertWbs.size()>firedWbs.size()?alertWbs.get(firedWbs.size()):alertWbs.get(alertWbs.size()-1);
		 			  }
		 				 
		 			  
		 			
		 			  // // QLog.getLogger().dLog(TAG,TAG, "Target index is:" +targetIndex);
		 			  
		 			 

			 	      if(targetWb==null)continue;
			 	      
		 			  sleeptime=getinitialSleepTime() ;
		 			  minDist=(int) (getAvs()/3.6*sleeptime/1000*turnFactor);
		 			  minDist =app.playBack?(int) (getAvs()/3.6*500/1000*turnFactor):minDist;
		 			  distForSayTurn=minDist; 
		 			   
 
		 			  targetRoadbook =targetWb.getRoadBook();
		 			  
 		 			 // // QLog.getLogger().dLog(TAG,TAG,"1 targetRoadbook: " +targetRoadbook ); 
		 			  
		 		 
 		 		  if( QiYouConstant.PV_INT_NAVI_SPEAK_MODEL==0 ){
		 			  int i =targetRoadbook.lastIndexOf("前方到达");
		 			 // // QLog.getLogger().dLog(TAG,TAG,"  targetRoadbook.lastIndexOf(前方到达): " +i ); 
		 			  if(i>0){
		 				 targetRoadbook =  targetRoadbook.substring(0,i); 
		 			  }
		 		  }
		 						
 		 	     // // QLog.getLogger().dLog(TAG,TAG,"2 targetRoadbook: " +targetRoadbook ); 
 		 	     
		 			  targetTurn =targetWb.getTurnFlag().toCHString();
		 			  targetTurn=targetTurn.equalsIgnoreCase(wpFlag.NORMAL.toCHString())?"":targetTurn.equalsIgnoreCase(wpFlag.CUST.toCHString())?"":targetTurn;
		 			 LATERTHEN_TURN =TextUtils.isEmpty(targetTurn)?targetTurn:LATERTHEN+targetTurn;
 		 			  alertDist=  (int) (targetWb.getBearDist()>0?targetWb.getBearDist():targetWb.getDistance());
 
		 			 if(targetWb.getTurnFlag()==wpFlag.MAXR){
 		 				   targetRoadbook += nextGeo+"，\n"+targetWb.getComment();
		 				  // // QLog.getLogger().dLog(TAG,TAG," find maxR" );
		 			 } else
			 			 if(firedWbs.size()+1<alertWbs.size()){
			 				 
			 				nextWb=alertWbs.get(firedWbs.size()+1);			 				
			 				if(nextWb==null)continue;
			 				if(nextWb.getTurnFlag()==wpFlag.MAXR){
			 					 if(firedWbs.size()+2<alertWbs.size()){
			 						nextWb=alertWbs.get(firedWbs.size()+2);		
			 					 }
			 				}
			 				nextGeo=null;
			 				 if (nextWb.getGeo()!=null && !TextUtils.isEmpty(nextWb.getGeo().toString(","))){
								nextGeo =  nextWb.getGeo().toString(",");
								nextGeo =  nextWb.getGeo().getStreet() +nextWb.getGeo().getStreetNo();
 							 }
 			 				 // // QLog.getLogger().dLog(TAG,TAG,"1 nextGeo: " +nextGeo );
			 				   nextGeo =(TextUtils.isEmpty(nextGeo)||nextGeo.length()<2)?"":"，\n到达"+nextGeo.replace("null", "");
//			 				  // // QLog.getLogger().dLog(TAG,TAG,"2 nextGeo: " +nextGeo );
			 				   String cmt =targetWb.getComment();
//			 				  // // QLog.getLogger().dLog(TAG,TAG," cmt: " +cmt );
			 				  cmt =  TextUtils.isEmpty(cmt)?"":"，\n到达"+cmt;
 			 				 
			 				  cmt =QiYouConstant.PV_INT_NAVI_SPEAK_MODEL==1?cmt:"";
			 				  targetRoadbook += nextGeo+cmt;
	 
			 			 }
		 			 
		 			 
		 			targetRoadbook =targetRoadbook.replace("null", "");
		 			
		 			
		 			  // QLog.getLogger().dLog(TAG,TAG, String.format("  target alertDist :%s, target turn is:%s,targetRoadbook is:%s",alertDist,targetTurn,targetRoadbook) );

 		 			
		 			
		 			firedWbs.add(targetWb);  //put it to chkOnWay,when it passed, put the target in
		 			
		 			
		 			sleeptime=getinitialSleepTime() ;
 		 			  
		 			   // QLog.getLogger().dLog(TAG,TAG, String.format(" maxAlertDist is:%s, minAlertDist:%s ,alertDist: %s",maxDist,minDist,alertDist) );
		 			  
		 			  if(alertDist>0 && alertDist>minDist)
		 			  {
		 				  alertDist =(int) (alertDist/4); 
			    		  alertDist=alertDist>maxDist?maxDist:alertDist;
			    		  alertDist=alertDist<minDist?minDist:alertDist;
		 			  }else if(alertDist<=minDist){  
		 				  
		 				  speakRoadBook(targetWb, targetRoadbook);  
		 				  
		 				  lastLeft =getLeftDistance(targetWb,alertDist);
		 				  distForSayTurn = distForSayTurn >alertDist?alertDist:distForSayTurn;
		 				  // QLog.getLogger().dLog(TAG,TAG, " 0 leftDistance: " +leftDistance+", lastLeft : " +lastLeft +", lastCnt "+ lastCnt +",getAvs() :" +	""+getAvs() +",alertDist:" +alertDist +", distForSayTurn:" +distForSayTurn);
		 				   
 		 				  if(lastLeft +alertDist>0){
 		 					  
 		 					  speakTurn( targetWb, getTurnDesc(lastLeft +alertDist ,targetTurn)/*String.format("前行%s ,%s", Utils.getFormatedDistance(lastLeft +alertDist),targetTurn)*/); 
 		 					
 		 					checkOnWay(targetWb); 
// 		 					sleeptime =(int) ((((alertDist+lastLeft-distForSayTurn)/(getAvs()/3.6))*1000)*(app.playBack?QiYouConstant.PLAYBACK_TIME_INTERVAL/QiYouConstant.MAX_GPS_SPAN:sleepFactor));
 		 					sleeptime =getAvailableSleepTime(alertDist+lastLeft-distForSayTurn);
 		 					if(sleeptime>0){
			 					      // QLog.getLogger().dLog(TAG,TAG," ----Sleep:" +sleeptime);
			 					 if(isNaviGood())
			 						 Thread.sleep(sleeptime); 
			 				}
 		 				  }
 		 				  
			 			  speakTurn(targetWb,targetTurn);
 
		 				 
			 			  lastLeft =getLeftDistance(targetWb,alertDist);
		 				  if(lastLeft +alertDist>0){		 					 	
 		 					 speakRoadBook(targetWb,String.format("前行%s ， %s, %s",Utils.getFormatedDistance(lastLeft +alertDist),LATERTHEN_TURN,targetRoadbook));  
		 				  }else{
		 					 speakRoadBook(targetWb, targetRoadbook);  
		 				  }
		 				
		 				  //TODO: sleep to the last distination
		 				  checkOnWay(targetWb); 
//		 				  sleeptime =(int) ((((alertDist+lastLeft)/(getAvs()/3.6))*1000)*(app.playBack?QiYouConstant.PLAYBACK_TIME_INTERVAL/QiYouConstant.MAX_GPS_SPAN:sleepFactor));
		 				 sleeptime =getAvailableSleepTime(alertDist+lastLeft);
		 				    // // QLog.getLogger().dLog(TAG,TAG," Sleep:" +sleeptime);
		 				 if(sleeptime>0)
		 					if(isNaviGood())
		 						Thread.sleep(sleeptime);
		 				 
		 				 if(checkForNewLocation(targetWb )){ 
		 					 
			 				 return;
			 			  }
		 				 
 
		 				 if(firedWbs.size() ==alertWbs.size()){
		 					 speakRoadBook(targetWb,"到达终点位置附近");  
		 				 }
			 			 
			 			  if(firedWbs.size() > alertWbs.size()){  //到达终点位置附近，重新寻找导航点
				 			   // QLog.getLogger().dLog(TAG,TAG, " 到达终点位置附近，重新寻找导航点   ...   " );
				 			  Thread.sleep(getinitialSleepTime());   
				 			  processNavigation(); 
				 			  return;
				 		   }
			 			
		 				 
		 				 
		 				  continue;
		 			  }
		    		
 		 			  distForSayTurn = distForSayTurn >alertDist?alertDist:distForSayTurn;
		    		  
		 			     // QLog.getLogger().dLog(TAG,TAG, " alertDist:" +alertDist +",sleeptime: "+sleeptime +",distForSayTurn:"+distForSayTurn);
		 			 
		 			  checkOnWay(targetWb); 
		 			  if(checkForNewLocation(targetWb )){ 
		 	 
			 				 return;
			 			  }
		 			  
		 			  updateUI(targetWb,"导航中...");
		 			  sayHi();
		 			  
		 			  lastLeft =getLeftDistance(targetWb,alertDist);
		 			  leftDistance =lastLeft;
							 			  
																 			    // QLog.getLogger().dLog(TAG,TAG, " lastLeft:" +lastLeft +",sleeptime: "+sleeptime);
																    
																 			    // QLog.getLogger().dLog(TAG,TAG, "1 leftDistance: " +leftDistance+", lastLeft : " +lastLeft +", lastCnt "+ lastCnt +",getAvs() :" +""+getAvs() +",alertDist:" +alertDist +", distForSayTurn:" +distForSayTurn);

		 				 
		 			  while(getAvs()>0 && lastLeft>0  && lastCnt>=tringCnt){
		 				 sleeptime= getinitialSleepTime(); 
		 				
		 				 if(isClosing)
		 					  if(checkForNewLocation(targetWb )){ 
		 			 
		 		 				 return;
		 		 			  } 
		 				   
		 				  lastLeft =getLeftDistance(targetWb,alertDist);
		 				  // // QLog.getLogger().dLog(TAG,TAG, " lastLeft:" +lastLeft +",lastCnt: "+lastCnt);
 		 				  if(lastLeft<=0 && lastCnt>=0){ //in alert zone
		 					  isClosing=true;
		 					  // // QLog.getLogger().dLog(TAG,TAG, "in alert zone, to speak...");
		 					  break; 
		 				  }
		 		          
		 				  if(checkForNewLocation(targetWb )){ 
		 		 
				 				 return;
				 			  } 
		 		         
		 		          lastLeft =getLeftDistance(targetWb,alertDist);
		 		          
		 						 
 		 		          if(leftDistance-lastLeft>=0){		 //接近目标					   
//		 					   lastLeft=leftDistance; 
		 					   lastCnt++; 
		 					   
		 					  if(lastLeft<0){ //in alertdist 
		 						 isClosing=true;
	 						 	 break;  
			 						 
			 					  }  
		 					  
		 				   }		 				   
		 				   else{  //远离目标
		 					   
		 					  isClosing=false;
		 					  
		 					  if(lastLeft<0 ){ //in alertdist
  
			 						if(lastLeft+alertDist>distForSayTurn){ //passed the target,between the target and say-turn point  
			 							 if(speakCnt==0){
				 			 				 speakRoadBook(targetWb,targetRoadbook);
				 						 }
					 				    break; 
					 				   }
			 						 
			 					  }  
			 					
		 					  if(lastLeft>0 && lastCnt<-2){  //out alert scope,to next
		 						
		 						 break; 
			 					 }
		 					  
		 					   if(lastCnt>0)lastCnt=0;
		 					   lastCnt--;
		 				   }
		 				   
		 				  
		 				   isClosing=lastCnt>0;
		 				   
																                        // // QLog.getLogger().dLog(TAG,TAG, "2 leftDistance: " +leftDistance+", lastLeft : " +lastLeft +", lastCnt "+ lastCnt +",getAvs() :" +""+getAvs() +",alertDist:" +alertDist);
		 			
		 				 leftDistance=leftDistance>lastLeft?lastLeft:leftDistance;
		 				   
		 				   if(  lastLeft>0 && isClosing &&getAvs()>0){
		 					  checkOnWay(targetWb); 
		 					   sleeptime  =(int) (((leftDistance/(getAvs()/3.6))*1000)*(app.playBack?QiYouConstant.PLAYBACK_TIME_INTERVAL/QiYouConstant.MAX_GPS_SPAN:1)) ;
		 					   if(sleeptime>30000)
		 						  if(/*!isWrongWayAlert*/isNaviGood()){                                                                  
		 						   speakDistTimeToTarget(sleeptime,leftDistance+alertDist);
		 						  }
 		 					   
		 					  sleeptime =getAvailableSleepTime(leftDistance);
		 					 if(QiYouConstant.DEVELOPER_MODE){
		 						   updateUI(targetWb,"  接近目标点,等待(s):" +sleeptime/1000);
		 					 }
		 					   
		 					   // // QLog.getLogger().dLog(TAG,TAG, " sleep:: " +sleeptime);
 					 			if(sleeptime>0){
 					 				if(isNaviGood()){
 					 					Thread.sleep(sleeptime);
// 					 					lastCheckNaviPoint =System.currentTimeMillis();//重新设定验证点时间
 					 				}
 					 			}
  
		 					 sayHi();
		 					 
		 				   }
		 				   
		 				   lastLeft =getLeftDistance(targetWb,alertDist);
		 				   
		 				   if(lastCnt<tringCnt){
		 					   // // QLog.getLogger().dLog(TAG,TAG, " it is away from the current target,trying next ");
		 					  updateUI(targetWb,"   远离目标点，重新计算导航目标。。。 " );
//		 					   findTarget();
// 		 					  wrongWayAlert();
		 					 speachNav("正在查找下一个导航点",1);
		 					  processNavigation();
		 					  return;
//		 					   continue;
		 				   }
		 				    
		 			  }
		 			  // to speak 
		 			 
		 			 
		 			 // // QLog.getLogger().dLog(TAG,TAG, " isClosing?  "+isClosing);
		 			
		 			 if(!isClosing &&
		 					 (lastCnt<tringCnt || lastLeft>0 && lastCnt<-2 )) {
		 				
		 				 // // QLog.getLogger().dLog(TAG,TAG, " it is away from the current target,isNotCheckedin :" +isNotCheckedin);
		 				 
		 				if(isNotCheckedin){
		 					
		 					 setFromLast(false);
		 					 processNavigation();
		 					 return;
		 				}
		 				 
		 				 setFromLast(false);
	 					 processNavigation();
	 					 return;
		 				 
		 			}
		 			 
		 			 sleeptime=  getinitialSleepTime();
		 			 // // QLog.getLogger().dLog(TAG,TAG, " isClosing?  "+isClosing +" , lastLeft,alertDist: "+lastLeft+","+alertDist); 
		 			 
		 			  if(isClosing ){
//		 					  ||lastLeft+alertDist<=0){
 
		 				 
		 				  int closeDist=lastLeft;  
//		 				 closeDist=lastLeft-alertDist; 
		 				 int lastCloseDist=closeDist;	
//		 				 targetTurn=  targetWb.getTurnFlag()==wpFlag.NORMAL?"":targetTurn;
		 				 while(isClosing
//		 				    		&& closeDist<0) {//in alert scope
		 						&& closeDist<=0) {//in alert scope
//		 				    		&& (closeDist+alertDist>distForSayTurn)){  //almost on target
//		 					sleeptime=  getinitialSleepTime();
		 					  
//			 				 
		 						 if(closeDist +alertDist<=distForSayTurn){ //between the say-turn point and the target   
		 							
		 							 if(closeDist +alertDist>0){
					 					 targetTurn=  String.format("前行%s米 ,%s", closeDist +alertDist,targetTurn); 
					 					 speakTurn(targetWb,targetTurn);
					 					 Thread.sleep((int) ((closeDist +alertDist)/(getAvs()/3.6)*1000));
					 					 speakRoadBook(targetWb,targetRoadbook);  
					 					 break;
		 							}
				 					 speakTurn(targetWb,targetTurn); 
				 					 speakRoadBook(targetWb,targetRoadbook);  
				 					 break;
				 				 }  
		 						 
		 						 if(!TextUtils.isEmpty(targetTurn) && closeDist +alertDist<2*distForSayTurn){
		 							 speakTurn(targetWb,String.format("前行%s，%s",Utils.getFormatedDistance(closeDist +alertDist),LATERTHEN_TURN));
 
		 						 }
			 					 
				 				 
		 						 checkOnWay(targetWb); 
//				 				sleeptime =(int) ((((alertDist+closeDist-distForSayTurn)/(getAvs()/3.6))*1000)*(app.playBack?QiYouConstant.PLAYBACK_TIME_INTERVAL/QiYouConstant.MAX_GPS_SPAN:sleepFactor));
				 				sleeptime =getAvailableSleepTime(alertDist+closeDist-distForSayTurn);
				 				if(sleeptime>0) 
				 					if(isNaviGood())
				 						Thread.sleep(sleeptime);
				 				else{
				 					speakTurn(targetWb,String.format("前行%s,%s", Utils.getFormatedDistance(closeDist +alertDist),LATERTHEN_TURN));
				 					
				 					break;
				 				}
				 				
			 					// // QLog.getLogger().dLog(TAG,TAG, String.format(" wait for turn, sleeptime %s,speakCnt:%s", sleeptime,speakCnt) );

		 					
			 				  sleeptime= 0;			 				  
		 				    
			 				  if(checkForNewLocation(targetWb )){ 
			 				 
					 				 return;
					 			  }  
		 				    	
		 				    	closeDist =getLeftDistance(targetWb,alertDist); 
//		 				    	isClosing =Math.abs(closeDist)<=Math.abs(lastCloseDist);
		 				    	isClosing =closeDist+alertDist<= alertDist+lastCloseDist && closeDist+alertDist>0;
		 				        // // QLog.getLogger().dLog(TAG,TAG, String.format(" real distance to target %s,lastCloseDist %s,  isClosing %s", closeDist+alertDist ,lastCloseDist+alertDist,isClosing) );
		 				    	lastCloseDist=closeDist;
		 				    	// // QLog.getLogger().dLog(TAG,TAG, String.format("  speakCnt:%s", speakCnt) );
//		 				    	updateUI(targetWb,"  距下个导航目标距离:  "+ closeDist );
		 				    	 if(QiYouConstant.DEVELOPER_MODE){
			 						   updateUI(targetWb,String.format("？？isclosing?%s，leftDist %s，alertDist %s", isClosing,closeDist,alertDist));
//			 						  speachNav("这是测试1",4);
//			 						  speakRoadBook(targetWb,"这是测试1");
			 					 }
		 				    	
//		 				    	if(isClosing ||closeDist+alertDist<0)break;
		 				    	 if(isClosing && speakCnt<3){
 			 				    		 
			 				    		  if( !app.playBack || speakCnt==0)
			 				    		  {// when playback/snavi,only speak once!!!
			 				    			 speakRoadBook(targetWb,String.format("前行%s，    %s,  %s",Utils.getFormatedDistance(closeDist +alertDist),LATERTHEN_TURN,targetRoadbook)); 
			 				    		   }
			 				    		 speakCnt++;
			 				    		  
		 				    		 }else{
		 				    			 break;
		 				    		 }
		 				    	
		 				    	 if(!isClosing)break;
		 				    	 
		 				    	 checkOnWay(targetWb); 
//			 					 sleeptime +=((closeDist/(getAvs()/3.6))*1000)*(app.playBack?QiYouConstant.PLAYBACK_TIME_INTERVAL/QiYouConstant.MAX_GPS_SPAN:sleepFactor);	
//			 					 sleeptime =(int) ((((alertDist+closeDist)/(getAvs()/3.6))*1000)*(app.playBack?QiYouConstant.PLAYBACK_TIME_INTERVAL/QiYouConstant.MAX_GPS_SPAN:sleepFactor));	
			 					sleeptime =getAvailableSleepTime(alertDist+closeDist);
			 					// // QLog.getLogger().dLog(TAG,TAG, String.format(" sleeptime %s,speakCnt:%s", sleeptime,speakCnt) );
			 					if(sleeptime>0)
			 						if(isNaviGood())
			 							Thread.sleep(sleeptime);
//			 				     Thread.sleep(getinitialSleepTime());
			 					closeDist =getLeftDistance(targetWb,alertDist); 
			 					lastCloseDist=closeDist;
			 					
			 					 
		 				    }
		 			
//		 				     Thread.sleep(getinitialSleepTime());
		 			  } 
		 			 if(speakCnt==0 && isNaviGood()){
//		 					 && lastLeft<=0){
//		 					 && lastLeft+alertDist>0)
		 				 speakRoadBook(targetWb,targetRoadbook);
		 			 }
		 			 
		 			 Thread.sleep(getinitialSleepTime());   
		 			 updateUI(targetWb," 开始下个导航点。。。。 " );
		 			 // // QLog.getLogger().dLog(TAG,TAG, "  goto next target...   " ); 
		 			 if(isNaviGood() && firedWbs.size() ==alertWbs.size()){
		 				 
	 					 speakRoadBook(targetWb,"到达终点位置附近");  
	 				 }
		 			 
		 			  if(firedWbs.size() > alertWbs.size()){  //到达终点位置附近，重新寻找导航点
			 			  // // QLog.getLogger().dLog(TAG,TAG, " 到达终点位置附近，重新寻找导航点 , goto next target...   " );
			 			  Thread.sleep(getinitialSleepTime());   
			 			  processNavigation(); 
			 			  return;
			 		   }
		 			
		 			   
		 		   }
		 		   
		 	 
		 		} catch (InterruptedException e) {
		 			// TODO Auto-generated catch block
		 			e.printStackTrace();
		 		} 
				
 
		    	app.isNaving=false;	
		    	exitNav();
			}}.start();
 }
 
 
 
 
 private void exitNav(){
	  // // QLog.getLogger().dLog(TAG , " try to stop the service...");
	 app.clearLastNavId();
	this.stopSelf();
 }
 private int getinitialSleepTime(){
 	 int sl=app.playBack?QiYouConstant.PLAYBACK_TIME_INTERVAL:QiYouConstant.MAX_GPS_SPAN;;
     // // QLog.getLogger().dLog(TAG,TAG, " get initial sleeptime: " +sl);
//	 return sl;
	 return app.playBack?QiYouConstant.PLAYBACK_TIME_INTERVAL/10:QiYouConstant.MAX_GPS_SPAN;
 }
 
 private int getAvailableSleepTime(float dist){
	 int sleeptime  =(int) (((dist/(getAvs()/3.6))*1000)*(app.playBack?QiYouConstant.PLAYBACK_TIME_INTERVAL/QiYouConstant.MAX_GPS_SPAN:1)) ; 
	   sleeptime=sleeptime/2; 
	   sleeptime =sleeptime>minSleeptime?sleeptime:0;
	   sleeptime=sleeptime>maxSleeptime?maxSleeptime:sleeptime; 
	   return sleeptime;
 }
 
 
 
 
// private boolean checkForNewLocation(Waypoint_bean targetWb, HashMap<String,Float> chkWps) throws InterruptedException{
 private boolean checkForNewLocation(Waypoint_bean targetWb) throws InterruptedException{
	 int sleeptime=  getinitialSleepTime();
	 long lastLocationTime=app.lastNaviLocation==null?0:app.playBack?app.lastNaviLocation.getExtras().getLong("wptime"):app.lastNaviLocation.getTime();
	   
	 while( app.lastNaviLocation==null ||lastLocationTime==app.lastNaviLocation.getTime() 
			   ||app.playBack && (lastLocationTime==app.lastNaviLocation.getExtras().getLong("wptime"))){
		   if(!app.playBack){
			   // // QLog.getLogger().dLog(TAG,TAG, " No location got, waiting for GPS...,sleep: " +sleeptime);
		   }
				Thread.sleep(sleeptime);
				
//			// // QLog.getLogger().dLog(TAG,TAG, "--------------- after sleep " );
			 
				sayHi();
			 if(!app.playBack)
				 updateUI(targetWb," 导航进行中...");	
			 
			  if(isNaviDone()){
					 // // QLog.getLogger().dLog(TAG,TAG + " to exit navigation"); 
					return true;
					 
				}
//			 if(sleeptime<5*getinitialSleepTime())
//				 sleeptime+=sleeptime/10;
//			 else
//				 sleeptime=getinitialSleepTime();
		  }

		  while(app.lastNaviLocation!=null &&  0==app.lastNaviLocation.getSpeed()){
			  if(!app.playBack){
				  // // QLog.getLogger().dLog(TAG,TAG, "  Not Moving... sleeptime: "+sleeptime);
			  }
			  Thread.sleep(sleeptime);
			  sayHi();
			  if(!app.playBack)
				  updateUI(targetWb," 静止中");
//			  if(sleeptime<5*getinitialSleepTime())
//					 sleeptime+=sleeptime/10;
//				 else
//					 sleeptime=getinitialSleepTime();
			  if(isNaviDone()){
					 // // QLog.getLogger().dLog(TAG,TAG + " to exit navigation"); 
					 return true;
					 
				}
		 }
		  
		  
		  
		   
		  return false;
		  
 }
 
 
 
 void checkOnWay(Waypoint_bean targetWb ) throws InterruptedException{
	 
	 
	
	 
	 if(app.lastNaviLocation!=null && app.lastNaviLocation.getSpeed()>0 && checkWps!=null && checkWps.keySet()!=null  && checkWps.keySet().size()>0 ){
			/*  float keyToCheck =getFloatKey((float)app.lastNaviLocation.getLatitude(),(float)app.lastNaviLocation.getLongitude());*/
			 /* float keyToCheck =getFloatKey((float)app.lastNaviLocation.getLatitude());*/
			   
			  String keyToCheck =getStringKey((float)app.lastNaviLocation.getLatitude(),(float)app.lastNaviLocation.getLongitude());
			 
			  boolean isExist=checkWps.keySet().contains( keyToCheck ) ; 
			  
			  if(isExist && isNotCheckedin){
				  isNotCheckedin=false;
			  }
			  
			  if(isNotCheckedin) return ;//not in the route ever
			  
			 /* if(!isExist 				 
					  && !canDistAlert()  //not reach last waypoint
					  && wrongDirectionCnt==0 //when wrong direction cnt>0, go on check for next direction
					  ){
					 // QLog.getLogger().dLog(TAG,   "     not reach the nextDist.......skip wrong way check..................."); 
					 return;
				  }*/
			  
			  if(wrongWayCnt==0){ //reset the lastCheckNaviDist, in case sleep dist in naviprocess
				  lastCheckNaviDist=app.sumNavDist;
			  }
				 
			  int chkCnt=0;
			  while (app.lastNaviLocation.getSpeed()>0 && !isExist && chkCnt<10  ||isWrongWayAlert){
				  
				  if(isNaviDone()){
						 // // QLog.getLogger().dLog(TAG,TAG + " to exit navigation"); 
						return;
						 
					}
				  chkCnt++;
				  
				  keyToCheck =getStringKey((float)app.lastNaviLocation.getLatitude(),(float)app.lastNaviLocation.getLongitude());
				  isExist=checkWps.keySet().contains( keyToCheck ) ;
				
				  if(isExist){
					  // // QLog.getLogger().dLog(TAG,TAG + String.format(" keytocheck %s exist",  keyToCheck)); 
					 break; 
				  }
				  
				  // // QLog.getLogger().dLog(TAG,TAG + String.format(" keytocheck %s not exist",  keyToCheck)); 
				  
				    
				  Thread.sleep(getinitialSleepTime());
				 
				  
				  long interVal=(long) ((avDist/(getAvs()/3.6))*1000) ; /*60000*/
				  // QLog.getLogger().dLog(TAG,  String.format("chkwps: missed wps check original interVal: %s",interVal)); 
				  
				  interVal =interVal>WRONG_WAY_MAX_INTERVAL? WRONG_WAY_MAX_INTERVAL:interVal;   
				  
		 
					  
				 if(wrongWayCnt>0){
					 if(wrongWayCnt<=2) {
						 interVal=WRONG_WAY_MIN_INTERVAL/2;
					 }else{
					  interVal-=15000*wrongWayCnt;
					  interVal=interVal<WRONG_WAY_MIN_INTERVAL/2? WRONG_WAY_MIN_INTERVAL/2:interVal;
					 }
				  }else {
					  interVal=interVal<WRONG_WAY_MIN_INTERVAL? WRONG_WAY_MIN_INTERVAL:interVal;
				  }
				
				   // QLog.getLogger().dLog(TAG,  String.format("chkwps: missed wps check  interVal: %s，wrongWayCnt: %s",interVal,wrongWayCnt)); 
				   // QLog.getLogger().dLog(TAG,  String.format("chkwps: lat wrongWayAlert, time pass:%s s, since last pass",(System.currentTimeMillis()-lastCheckNaviPoint)/1000 ) ); 
					
//				   if( isMaxDistAlert() || canDistAlert() && lastCheckNaviPoint>0 && System.currentTimeMillis()-lastCheckNaviPoint> interVal ){ 
				   if( canDistAlert() && lastCheckNaviPoint>0 && System.currentTimeMillis()-lastCheckNaviPoint> interVal ){ 

//					 // QLog.getLogger().dLog(TAG,  String.format("chkwps: lat wrongWayAlert, time pass:%s s, since last pass",(System.currentTimeMillis()-lastCheckNaviPoint)/1000 ) ); 
					
					    wrongWayCnt++; 
					   
					    isWrongWayAlert=wrongWayCnt>=WRONG_WAY_ALERT_CNT;
					   
 					  if(isWrongWayAlert) {
						 updateUI(targetWb,WRONG_WAY ); 
					  }
					 
 					  wrongWayAlert();
					 
					 lastCheckNaviPoint =System.currentTimeMillis();
 					 lastCheckNaviDist =app.sumNavDist;
					
					 
				  } 
				    
			  }
			  
			  

			  if(isExist){
				   
				  
				  lastCheckNaviPoint =System.currentTimeMillis();
				  lastExistNaviDist=app.sumNavDist;
				  lastCheckNaviDist =app.sumNavDist;
//				  isWrongWayAlert=false;
				  isNotCheckedin =false;
 
				  if(app.playBack){
 					  return;
				  }
				  
				 
				  lastDist=currentDist;
				  currentDist = checkWps.get(keyToCheck)[0];
				  nextDist = checkWps.get(keyToCheck)[1];
                  
//				  // QLog.getLogger().dLog(TAG,  String.format(" Existed, keyToCheck : %s,currentDist = %s ,lastDist =%s", keyToCheck,  currentDist,lastDist  ));  

				  
				  // QLog.getLogger().dLog(TAG,  String.format(" Existed, wrongDirectionCnt : %s,currentDist -lastDist = %s ,nextDist =%s", wrongDirectionCnt, (currentDist -lastDist),nextDist ));  
				  
				 if(currentDist<lastDist){
					  // // QLog.getLogger().dLog(TAG,  String.format("currentDist -lastDist = %s ,wrongDirectionCnt =%s ", (currentDist -lastDist),wrongDirectionCnt ));  
 				    wrongDirectionCnt++;
				 }else  if(currentDist>lastDist) {
					 wrongDirectionCnt=0;
					  isWrongWayAlert=false;
				 }
				 
				  if(wrongWayCnt>0 && wrongDirectionCnt==0 ){
					  speachNav("导航路线正常。。。",1);
					  updateUI(targetWb,"导航进行中..." ); 
					 
				  }
				  
				  wrongWayCnt=0;
			  }
			  
			  if(wrongDirectionCnt>4){
				  // // QLog.getLogger().dLog(TAG,  String.format("Wrong direction Alert! wrongDirectionCnt =%s", (currentDist -lastDist)  ));  
				  isWrongWayAlert=true;
				  speachNav("警告：方向错误",1); 
				  vibratorAlert(vibratorWrongWayPattern,-1);
				  wrongDirectionCnt=0;
			  }
			  
			  
			  
			 
			  
			  
			  
	 }	  
//			  // // QLog.getLogger().dLog(TAG,  String.format("chkwps: chkWps.keySet().contains :%s,value is %s",checkWps.keySet().contains( keyToCheck), checkWps.get( keyToCheck) )  );
//
////			  // // QLog.getLogger().dLog(TAG,  String.format("chkwps: lat tocheck new location:%s,%s,eixst? %s",keyToCheck,getFloatKey((float)app.lastNaviLocation.getLongitude()),isExist));
//			  // // QLog.getLogger().dLog(TAG,  String.format("chkwps: lat tocheck new location:%s,eixst? %s",keyToCheck, isExist));
 
 }
 
 
 void initialParameters(){
	   lastTime_avs=0;
	   last_avs=0f;
	   wrongWayCnt=0; 
	   isNotCheckedin=true;
	    isWrongWayAlert=false;
	    lastCheckNaviPoint=0;
	   lastDist=0;
	   wrongDirectionCnt=0;
	   currentDist=0;
	   nextDist=0;
	   lastCheckNaviDist=0;
	   lastExistNaviDist=0;
 }

 
 
 
 /*
  * km/h
  */
 private float getAvs(){
	
//	 float avs=0f;
	  if(!app.playBack && System.currentTimeMillis()-lastTime_avs<5000){
//		  lastTime_avs=System.currentTimeMillis(); //its bug!!!!! cause avs using old value, not updated in time 
		   // // QLog.getLogger().dLog(TAG,TAG," return last avs:" +last_avs);
		  return last_avs>0?last_avs: 8 ;	 
	  }
	  
	 last_avs=app.getAVS();
	 
	 if(app.playBack) return 20 ;//last_avs>0?last_avs:20; 
	 
	 float lastSpeed= (float) (app.lastNaviLocation==null?0:app.lastNaviLocation.getSpeed()*3.6);
// // QLog.getLogger().dLog(TAG,TAG," app.lastNaviLocation.getSpeed()*3.6:" +lastSpeed);
//	   if(app.playBack)
//		   avs =app.getCurrentTrack().getTrackBean().getCAvs();
//	   else
//	   avs  = app.getRecordingTrack().getTrackBean().getCAvs();
	 last_avs  = app.getRecordingTrack().getTrackBean().getAvs(); 
//	   // // QLog.getLogger().dLog(TAG,TAG, "  app.getCurrentTrack().getTrackBean().getAvs():   "+app.getCurrentTrack().getTrackBean().getAvs() );
		  
// 	   // // QLog.getLogger().dLog(TAG,TAG," app.getRecordingTrack().getTrackBean().getAvs():" +last_avs);
//	   avs=avs >app.getAVS()?avs:app.getAVS();
	 
	 
//	 last_avs=last_avs>0?last_avs:app.getAVS();  // app.getAVS() 可能比较大。。。
//	   // // QLog.getLogger().dLog(TAG,TAG," app.getAVS():" +app.getAVS());
	   
	 last_avs =last_avs>lastSpeed?last_avs:lastSpeed;
	   // // QLog.getLogger().dLog(TAG,TAG," return avs:" +last_avs);
	   // // QLog.getLogger().dLog(TAG,TAG,String.format("avs is %s,last speed is %s,return avs is %s"   ,app.getRecordingTrack().getTrackBean().getAvs(), lastSpeed, last_avs));
	   last_avs =  last_avs>0?last_avs: 8 ;
	  
	 lastTime_avs=System.currentTimeMillis();
	   
     return     last_avs ;
//	   return (float) (return_speed>0?return_speed:app.lastNaviLocation==null?0:app.lastNaviLocation.getSpeed()*3.6);
		   
		   
 } 
 
 
 
 
 private int getLeftDistance(Waypoint_bean targetWb,int alertDist){
	 Location targetLoc;
	  int distance=0;
//	  int radius=0; 
//	  radius=(int) targetWb.getBearDist(); 
	  targetLoc =new Location("fire");	  
	  targetLoc.setLatitude(targetWb.getLatitude());
	  targetLoc.setLongitude(targetWb.getLongitude()); 
	  distance= (int) app.lastNaviLocation.distanceTo(targetLoc);
	 return (int) (distance-alertDist - distFactor*getAvs()/3.6*getinitialSleepTime()/1000); // 10*getAvs()*getinitialSleepTime(): 修正距离，+6个定位时间的距离
 }
 
 
// private void findTarget(){
// // // QLog.getLogger().dLog(TAG,TAG, " trying to Find the target ");
//	  
// }
// 
 
 /**
  * check can sleep during navi process
  * if wrongwaycnt >1, or wrongdirection then return false
  * @return
  */
private boolean isNaviGood(){
	return  wrongWayCnt<=1                               // not in wrong way
			&& !isWrongWayAlert && wrongDirectionCnt==0; //with right direction
}
 
 private void validingWayAlert(){
//	 if(!app.playBack)
//		if(isWrongWayAlert)
	 if(wrongWayCnt > 1  ){
		 	speachNav("请检查导航路线是否正常...",1);//wrongwaycnt=2
	 }else{
			speachNav("正在检查导航路线...",1); //wrongwaycnt=1
	 }
 }

 private void wrongWayAlert(){
 
	  // QLog.getLogger().dLog(TAG,  String.format("chkwps: check dist can alert,wrongWayCnt is %s, minDistance is : %s",wrongWayCnt ,getMinDist()));
	 // // QLog.getLogger().dLog(TAG,  String.format("chkwps: canDistAlert() : %s",canDistAlert())); 
 
	/* if(!canDistAlert()){  
		 return;
	 }*/
	 
	 if(/*isWrongWayAlert*/wrongWayCnt > INT_START_ALERT_CNT){
		  speachNav("警告：偏离原设定路线",1); 
		  vibratorAlert(vibratorWrongWayPattern,-1);
		 
	 }else{
		 validingWayAlert();
	 }
	 
	/* if(wrongWayCnt==0){
		   validingWayAlert();
		   
	 }
	 else if(wrongWayCnt >= WRONG_WAY_ALERT_CNT  ){ 
		   // // QLog.getLogger().dLog(TAG,  String.format("chkwps: speach alert,wrongWayCnt : %s",wrongWayCnt));  
		   speachNav("警告：偏离原设定路线",1);
		  
		   vibratorAlert(vibratorWrongWayPattern,-1);
	 }*/
 }
 
 /**
  * get next roadpoint dist
  * @return next roadpoint dist
  */
 private float getMinDist(){
//	 return wrongWayCnt>0?avDist:avDist*WRONG_WAY_ALERT_AVDIST_CNT;
//	 return nextDist>0?nextDist:wrongWayCnt>0?avDist:avDist*WRONG_WAY_ALERT_AVDIST_CNT;
//	 return wrongWayCnt>0?avDist/**1.5f*/:nextDist;
	 
	 switch(wrongWayCnt){ 
	 	 case 0: return (avDist>nextDist?avDist:nextDist)*WRONG_WAY_ALERT_AVDIST_CNT +minDistPlus ;
		 case 1: return (avDist>nextDist?avDist:nextDist)*WRONG_WAY_ALERT_AVDIST_CNT +minDistPlus ;
		// case 2: return (avDist>nextDist?avDist:nextDist)*WRONG_WAY_ALERT_AVDIST_CNT +minDistPlus ;
		 
		 default: return (avDist>nextDist?avDist:nextDist) +minDistPlus;
	 }
	 
	 
// 	 return wrongWayCnt==0?(avDist>nextDist?avDist:nextDist)*WRONG_WAY_ALERT_AVDIST_CNT:avDist;
	  
 }
 /**
  * distance limit for alert
  * 
  */
 private boolean canDistAlert(){
	    // QLog.getLogger().dLog(TAG,  String.format("chkwps: getMinDist() : %s,app.sumNavDist:%s, lastCheckNaviDist: %s, lastExistNaviDist%s",getMinDist(),app.sumNavDist,lastCheckNaviDist,lastExistNaviDist ));  
	    // QLog.getLogger().dLog(TAG,String.format("wrongWayCnt ?%s, can Dist Alert? %s", wrongWayCnt,app.sumNavDist - (wrongWayCnt>0?lastCheckNaviDist:lastExistNaviDist)>getMinDist()));
	    return app.sumNavDist - (wrongWayCnt>0?lastCheckNaviDist:lastExistNaviDist)>getMinDist();
 }
 
/* private boolean isMaxDistAlert(){
	 // // QLog.getLogger().dLog(TAG,  String.format("chkwps: getMinDist() : %s,app.sumNavDist:%s, lastCheckNaviDist: %s, lastExistNaviDist%s",getMinDist(),app.sumNavDist,lastCheckNaviDist,lastExistNaviDist ));  
	return wrongWayCnt ==0 && (app.sumNavDist - (wrongWayCnt>0?lastCheckNaviDist:lastExistNaviDist)>avDist*4);
 }*/
 
 
 private void speakDistTimeToTarget(long waitTime,int distance){
	 if(isWrongWayAlert)return;
//	 String format = "距离下个位置还有%s,预计需要时间%s";
	 String	format = "继续前行%s，预计需要时间%s";
	 String time = Utils.getTimeCnt4Read(waitTime,true);
	 time = TextUtils.isEmpty(time) ? "少于一分钟": time;
	 String distTime=String.format(format,Utils.getFormatedDistance(distance) ,time  );
	 // // QLog.getLogger().dLog(TAG,TAG, distTime);
	 speachNav(distTime,1);
	 
 }
 private String getTurnDesc(float leftDist,String targetTurn){
		  return (leftDist>MIN_TURN_DIST)?String.format("前行%s ,%s", Utils.getFormatedDistance(leftDist),targetTurn):targetTurn;

 }
 private void speakRoadBook(Waypoint_bean targetWb,String nextRoodbook){
	 // // QLog.getLogger().dLog(TAG,TAG, " distance is:" +app.getRecordingTrack().getTrackBean().getDistance());
	 // // QLog.getLogger().dLog(TAG,TAG, " Now it is the time for Speak:" +nextRoodbook);
	  
 	 if(/*isWrongWayAlert*/!isNaviGood())return;
//	 if(isFirstWaypoint)return;
//	 if(wrongDirectionCnt>0)return; 
 	 
 	 if(targetWb.getSumDist()==0) return;
 	 
	 speachNav(nextRoodbook,1);
 	 
	 updateUI(targetWb,targetWb.getRoadBook() );
	 lastSay=System.currentTimeMillis();
 }
 private void speakTurn(Waypoint_bean targetWb,String targetTurn){
	 // // QLog.getLogger().dLog(TAG,TAG, " distance is:" +app.getRecordingTrack().getTrackBean().getDistance());
	 // // QLog.getLogger().dLog(TAG,TAG, " Now it is the time for Speak turn right now:" +targetTurn);
 
	 if(/*isWrongWayAlert*/!isNaviGood())return;
	 if(targetWb.getSumDist()==0) return;
//     if(wrongDirectionCnt>0)return;
 	
	 updateUI(targetWb,targetTurn);
	 speachNav(targetTurn,2);
 
//	 if(targetWb.getTurnFlag()==wpFlag.CHECK
//			 ||targetWb.getTurnFlag()==wpFlag.REST
//			 ||targetWb.getTurnFlag()==wpFlag.TENT
//			 ||targetWb.getTurnFlag()==wpFlag.TURNLEFT
//			 ||targetWb.getTurnFlag()==wpFlag.TURNRIGHT
//			 ){
//		  		vibratorAlert(getVibratorPattern(targetWb.getTurnFlag())/*vibratorTurnPattern*/,-1);
//	 		}
	  if(targetWb.getTurnFlag()!=wpFlag.CUST && targetWb.getTurnFlag()!=wpFlag.NORMAL){
		  vibratorAlert(getVibratorPattern(targetWb.getTurnFlag())/*vibratorTurnPattern*/,-1);
	  }
	 
	 
	 lastSay=System.currentTimeMillis();
 }
 long [] getVibratorPattern (wpFlag flag){
	
	 switch (flag){
	 case  TURNRIGHT: return  new long[]{100,500,100,500};
	 case  TURNLEFT: return  new long[]{200,500,200,500,200,500};
	 default :return new long[]{50,300};
	 }
	 
	// if(flag==wpFlag.TURNLEFT) {100,500,100,500};
 }
 
 private void updateUI(Waypoint_bean wb,String msg){
	 if(!app.canSendLocation2UI || wb==null)return;
	 if(wrongWayCnt>1) msg=WRONG_WAY;
	 Location loc = new Location("nav");
		Bundle bd = new Bundle(); 
		bd.putString(QiYouConstant.NEW_NAVIFO_MSG, msg);
		bd.putInt(QiYouConstant.NEW_NAVIFO_DIST_PROGRESS, (int)(wb.getSumDist()/totalDist*100));
		loc.setExtras(bd);
		loc.setLatitude(wb.getLatitude());
		loc.setLongitude(wb.getLongitude());
	app.naviUI(loc, msg);
 }
 
 
  
 
/*     
   public boolean addProximityAlert(double lat, double lon,String roadBook, final long eventID, int requestCode) { 
//	   registerReceiver(new ProximityIntentReceiver(), getIntentFilter(requestCode));
 
 	   // // QLog.getLogger().dLog(TAG,TAG, String.format("add new alert to Proximity alert list, lat %s lon %s requestCode %s",lat,lon,requestCode ) );
	   return true;
	 }*/
 
   
    private void sayByebye(){ 
    	 // // QLog.getLogger().dLog(dTAG,TAG + " 导航结束");
    	if(!app.playBack){
    	 speachNav("导航结束",1);
    	}
    }
    
    private float totalDist=0.001f;
    
    private void sayHello(){ 
	    String summary="";
	    Track	gpxTrack;
//	    speachNav("导航开始, "+"导航路径ID " +app.naviTrackId );
//	    speachNav("导航开始" );
	    if(app.naviTrackId>0){
			gpxTrack=app.getTrackCache().get(app.naviTrackId);
			if(gpxTrack==null)return;
			float spd=app.getAVS();
			spd=spd>0?spd:16;
			
			String time = Utils.getTimeCnt4Read((long) ((gpxTrack.getTrackBean().getDistance()/ ( spd/*getAvs()*/ /*app.getAVS()*//3.6))*1000l) , false);
			 time = TextUtils.isEmpty(time) ? "少于一分钟": time;
			 
			summary=String.format("路线%s,%s。",
					gpxTrack.getTrackBean().getName(),
      				gpxTrack.getGpxDistTime()+
      				String.format("预计历时%s。", time)
					);
			 
			 totalDist+=gpxTrack.getTrackBean().getDistance();
	    }
	    else{
	    	 speachNav("导航轨迹加载错误",1);
	    	 sayByebye();
	    	 exitNav();
	    }
	    	/*
		    for(Integer i:app.getGpxShowingTracks()){
			  	gpxTrack=app.tracks_cached.get(i);
		//	 if(gpxTrack!=null)
		//		dist+=gpxTrack.getTrackBean().getDistance();
		      summary+= String.format("路线%s,%s。",
						gpxTrack.getTrackBean().getName(),
						gpxTrack.getGpxDistTime()
						); 
			 totalDist+=gpxTrack.getTrackBean().getDistance();
			}*/
	    
	    String pref = app.playBack ? "" : "导航开始";
	 	  speachNav( pref  + summary,0);
	// 	String sumary =String.format("路程全长%s公里，预计时间", args)
	 	 lastSay=System.currentTimeMillis();
	   	 // // QLog.getLogger().d(dTAG,TAG + " 导航开始");
   	 
   } 
	
    @Override
    public void onDestroy() {
    	   // // QLog.getLogger().dLog(dTAG,TAG + "naviSvc Services onDestory");
//    	  Log.i(dTAG,TAG + " ------------------------------------------------------Navi Services onDestory");
    	if(vibrator!=null){
    		vibrator.cancel();
    	}
    	  app.naviTrackId=-1;
    	  app.isNaving=false;	
    	  sayByebye();
    	
    }


	public boolean isFromLast() {
		return mIsFromLast;
	}


	public void setFromLast(boolean mIsFromLast) {
		this.mIsFromLast = mIsFromLast;
	}
	private long lastSay=0;
	private String HI="导航进行中";
	private void sayHi(){
		  
		if(System.currentTimeMillis() -lastSay>5*60*1000){
			if(isNaviDone()){
				 // // QLog.getLogger().dLog(TAG,TAG + " to exit navigation");
				exitNav();
			}
			 speachNav(HI,0);
			 lastSay=System.currentTimeMillis();
		}
	}
	
	private boolean isNaviDone(){
		
		if(app.isNavPaused){
			speachNav("导航暂停",1);
		}
		
		while(app.isNavPaused){
			 try {
				Thread.sleep(3000);
//				updateUI(null,"导航暂停");
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		 } 
		
//		  // // QLog.getLogger().dLog(TAG, " navi track id "+ naviId +", app.naviTrackId " +app.naviTrackId);
		    if(app.naviTrackId !=naviId){
		    	  // // QLog.getLogger().dLog(TAG, " navi need to be stoped.");
		    	this.stopSelf();
		    	return true;
		    }
		
		
		boolean isRecording =app.getRecordingTrack().getTrackBean().getStatus()==TrackStatus.RECORDING;
		isRecording =isRecording ||app.getRecordingTrack().getTrackBean().getStatus()==TrackStatus.PAUSED;
		boolean isPlayback =app.playBack &&	!app.playBackStopped;
        // // QLog.getLogger().dLog(TAG,  String.format("checkStatus: isRecording :%s,isPlayback:%s,app.isNaving: %s",isRecording,isPlayback,app.isNaving));
	    boolean isExit =!(isRecording || isPlayback) || !app.isNaving;   
	    
	    
	    if(isExit)
	    	exitNav();
	    else 
	    	return false;
	    
		return !(isRecording || isPlayback) || !app.isNaving;
	}
private void speachNav(String words,int priority){
	if(QiYouConstant.PV_INT_NAVI_SPEAK_MODEL!=2)
		app.speech(words,priority);
	 
}

 

 private void getChkWps(){	
	
		new Thread(){
			
			@Override
			public void run() {
				Track gpxTrack=null;		 
				 long starttime=System.currentTimeMillis();
//					HashMap<String,Float> wps = new HashMap<String,Float>();
//					checkWps = new HashMap<String,Float>();
				 checkWps = new HashMap<String,Float[]>();
//					Location loc;
//					 // // QLog.getLogger().dLog(TAG,  String.format("chkwps: lat begin......................"));
// 					int wpsCnt=0;
					if(app.naviTrackId>0){
						app.setLastNavId();		
//						gpxTrack=app.tracks_cached.get(app.naviTrackId);
						gpxTrack=app.getTrackCache().get(app.naviTrackId);
						if(gpxTrack!=null){
//							for(Waypoint_bean wb:gpxTrack.getTrackBean().getTrkseg()){
							Waypoint_bean wb;
							Waypoint_bean nextWb = null;
							float nextd=0;
							for(int i=0;i<gpxTrack.getTrackBean().getTrkseg().size();i++){
								wb =gpxTrack.getTrackBean().getTrkseg().get(i);
								if(wb!=null){
									/*if(wb.getTime()>=startWb.getTime() && wb.getTime()<=targetWb.getTime() ||
											wb.getSumDist()>=startWb.getSumDist() && wb.getSumDist()<=targetWb.getSumDist()){*/ 
										
//										// // QLog.getLogger().dLog(TAG,  String.format("chkwps: lat-lng: %s",getStringKey(wb.getLatitude() ,wb.getLongitude())));
										String key=getStringKey(wb.getLatitude() ,wb.getLongitude());
										nextd=0;
										if(i<gpxTrack.getTrackBean().getTrkseg().size()-1) {
											nextWb = gpxTrack.getTrackBean().getTrkseg().get(i+1);											
											nextd = nextWb!=null?/*nextWb.getSumDist()-wb.getSumDist()*/
													(float)Utils.getDistanceFromXtoY(wb.getLatitude(), wb.getLongitude(),nextWb.getLatitude(),nextWb.getLongitude())
													:0;
													
										
										}
										 if(nextd>500){
											 insertMoreKeys(wb,nextWb);
										 }else
											 if(!checkWps.containsKey(key) || checkWps.get(key)[0]<wb.getSumDist()){
											 
												 checkWps.put(key,new Float[]{wb.getSumDist(),nextd});
											
												 // QLog.getLogger().dLog(TAG,  String.format("build chkwps: lat-lng: %s,sumdist is %s,nextDist is %s  " ,key,checkWps.get(key/*getStringKey(wb.getLatitude(),wb.getLongitude())*/)[0],	checkWps.get(key/*getStringKey(wb.getLatitude(),wb.getLongitude()*/)[1] ));
											
										}
//										// QLog.getLogger().dLog(TAG,  String.format("build chkwps: lat %s,lng %s",wb.getLatitude() ,wb.getLongitude()));
 
										/*try{
										
										}catch(Exception e){
											Utils.logStackTrace(e, TAG);
										}*/
// 										wpsCnt++;  

									/*}else if( wb.getTime()>targetWb.getTime() || wb.getSumDist()>targetWb.getSumDist()){
										break;
									}*/
								}
							} 
							
							/*	avDist =(targetWb.getSumDist() - startWb.getSumDist())/wpsCnt;*/
							if(checkWps.keySet()!=null && checkWps.keySet().size()>0)
								avDist =(gpxTrack.getTrackBean().getDistance())/checkWps.keySet().size();
//							// // QLog.getLogger().dLog(TAG, "build chkwps cost time:(s) " +(System.currentTimeMillis()-starttime)/1000);
//							 // // QLog.getLogger().dLog(TAG, " build wps size:  " +checkWps.keySet().size());
                                 // QLog.getLogger().dLog(TAG, String.format(" track wps size: %s ,check key size %s,avDist: %s " ,gpxTrack.getTrackBean().getTrkseg().size(),checkWps.keySet().size(),avDist));
							 
                                 minDistPlus =/*(avDist/100f)**/avDist;
						}
						
			
						
					}
					 
				 
			}}.start(); 
		 
	}
 
 
 
 
 void insertMoreKeys(Waypoint_bean wb,Waypoint_bean nextWb){
	 
	 Waypoint_bean midWb = new Waypoint_bean();
	 
	 midWb.setLatitude((wb.getLatitude()+nextWb.getLatitude())/2);
	 midWb.setLongitude((wb.getLongitude()+nextWb.getLongitude())/2);
	 midWb.setSumDist(wb.getSumDist()+(nextWb.getSumDist()-wb.getSumDist())/2);
	 
	 String key=getStringKey(midWb.getLatitude() ,midWb.getLongitude());
	 float nextd =  (float)Utils.getDistanceFromXtoY(wb.getLatitude(), wb.getLongitude(),
			 									midWb.getLatitude(),midWb.getLongitude());
		

	
				
	 if(nextd<500  && nextd>200	 && (!checkWps.containsKey(key) || checkWps.get(key)[0] <midWb.getSumDist())){
		 
			checkWps.put(key,new Float[]{wb.getSumDist(),nextd});
			     // QLog.getLogger().dLog(TAG, String.format(" add mid wb key: %s, sumdist %s,nextd %s  " , key,wb.getSumDist(),nextd));
		}
	
	   
	  if(nextd<5000 && nextd>=500){
		  
		 insertMoreKeys(wb,midWb );
	 }
	 
	 
	 key=getStringKey(midWb.getLatitude() ,midWb.getLongitude());
	  
	 nextd =  	(float)Utils.getDistanceFromXtoY(midWb.getLatitude(),midWb.getLongitude()
			 								,nextWb.getLatitude(), nextWb.getLongitude()) 	;
				 	
				
	 if(nextd<500 && nextd>200 &&(!checkWps.containsKey(key) || checkWps.get(key)[0]<midWb.getSumDist())){
		 
			checkWps.put(key,new Float[]{midWb.getSumDist(),nextd});
			   // QLog.getLogger().dLog(TAG, String.format(" add mid wb key: %s, sumdist %s,nextd %s  " , key,midWb.getSumDist(),nextd));
		}
	  
 
	 if(nextd<5000 && nextd>=500){
		  
		 insertMoreKeys(midWb,  nextWb);
	 }
	 
	 
 }
 
  
 private String getStringKey(float lat,float lng){
	 float rd=1000f;
	 String rt=Math.round((lat*rd))/ rd +"-"+ Math.round((lng*rd))/ rd; 
	
//	 String rt=Math.round((lat*app.rd))/app.rd +"-"+ Math.round((lng*app.rd))/app.rd; 
//	// // QLog.getLogger().dLog(TAG,  String.format("chkwps: lat +lng:%s",rt));
	return rt;
} 
 
 private void vibratorAlert(long [] pattern,int repeatCnt ){
	 
	 if(vibrator!=null && !QiYouConstant.PV_BL_NAVI_VIBRATOR_ON)return;
	 
//     long [] pattern = {100,400,100,400};   // 停止 开启 停止 开启   
	 vibrator.cancel();  
     vibrator.vibrate(pattern,repeatCnt);           //重复两次上面的pattern 如果只想震动一次，index设为-1   
     
 }
 

}
