package kr.gmtc.tss.data;

import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentSkipListSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import kr.gmtc.tss.area.MarineAreaLoader;
import kr.gmtc.tss.data.vo.SetDynamicVO;
import kr.gmtc.tss.util.vo.DynamicVO; 

public class TargetManageRunnable implements Runnable {


	private Logger logger = LoggerFactory.getLogger(this.getClass());

	Queue<DynamicVO> dynamicVoQueue;
	Queue<SetDynamicVO> dynamicInsertQueue;
	private int listChunkSize=100; 
	private boolean isRunning = false;	

	private MarineAreaLoader marineAreaLoader;
	private int exceptCnt=0;

	private int dynamicSetSize;
	private int dynamicRemoveUnitSize;

	private long sleepMillis;
	
	
	private Comparator<SetDynamicVO> comparator = Comparator.comparingLong(v -> v.timeStamp);
//	private Comparator<SetDynamicVO> comparator = Comparator.comparingLong(v -> ((LocalDateTime)v.getDateTime()).toInstant(ZoneOffset.ofHours(9)).toEpochMilli());
//	private Comparator<SetDynamicVO> comparator = Comparator.comparing( ,(a,b) -> a.getdattime())
//	Set<SetDynamicVO> dynamicSet = ConcurrentSkipListMap.n.newKeySet(10000);
//	ConcurrentSkipListSet<SetDynamicVO> dynamicSet = new ConcurrentSkipListSet<SetDynamicVO>();
//	ConcurrentSkipListSet<SetVo> dynamicSet = new ConcurrentSkipListSet<SetVo>();
	ConcurrentSkipListSet<String> dynamicSet = new ConcurrentSkipListSet<String>();
//	
	
	
	public TargetManageRunnable(Queue<DynamicVO> dynamicVoQueue, Queue<SetDynamicVO> dynamicInsertQueue,MarineAreaLoader marineAreaLoader, int dynamicSetSize, int dynamicRemoveUnitSize, int listChunkSize, long sleepMillis) {
		this.dynamicVoQueue=dynamicVoQueue;
		this.dynamicInsertQueue=dynamicInsertQueue;
		this.marineAreaLoader=marineAreaLoader;
		this.dynamicSetSize=dynamicSetSize;
		this.dynamicRemoveUnitSize=dynamicRemoveUnitSize;
		this.listChunkSize=listChunkSize;
	}
	
	@Override
	public void run() {
//		ConcurrentSkipListSet<SetDynamicVO> dynamicSet = new ConcurrentSkipListSet<SetDynamicVO>(comparator);
//		
		System.out.println("runn");
		isRunning=true;
		
		while (isRunning) {
			
			try {
				int loopCnt=0;
				if(dynamicVoQueue.size()>listChunkSize) {
					loopCnt=listChunkSize;
				}else {
					loopCnt=dynamicVoQueue.size();
				}
				
				DynamicVO [] chunkArr = new DynamicVO[loopCnt];
				
				for (int i = 0; i < loopCnt; i++) {
					chunkArr[i]=dynamicVoQueue.poll();
				}
				
				
				for (int i = 0; i < chunkArr.length; i++) {
//					parseAndEnqueue(chunkArr[i]);	
//					chunkArr[i].getDynamicVO()
					putQueueData(chunkArr[i]);
					
				}
				
			} catch (Exception e) {
//				if (e.getMessage() != null) {
					logger.info("[TargetManager] Parsing Error Message : " ,e);
//				} else {
////					logger.info("[ParserThread] Parsing Error Packet Message :" + packetMsg);
//					logger.info("[ParserThread] Parsing Error Call Stack" ,e);
//					
//				}
			} 
			
			
			sleep(sleepMillis);
			
		}
	}

	
	private void putQueueData(DynamicVO dynamicVO) {
		
		removeOverCountQueue();
		
		SetDynamicVO vo = new SetDynamicVO(dynamicVO);
		String key=vo.getDateTime().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))+vo.getShipID();//+vo.getLongitude()+vo.getLatitude();
//		SetVo setVo = new SetVo(key);
		
		//Set에 안 담겨 있는경우에는 insert 큐에 입력(중복 방지)
		if(!dynamicSet.contains(key)) {
			dynamicSet.add(key);
			
			vo.setMarineAreaId(marineAreaLoader.getMarineAreaId(vo.getLongitude(), vo.getLatitude()));
			
//			if(!vo.isInserted()) {
				dynamicInsertQueue.add(vo);
				
				
//				vo.setInserted(true);
//			}else {
//				logger.info(vo.getString());
//			}
			
		}else {
			logger.debug("except msg : "+vo.getString());
			exceptCnt++;
		}
		
		
		
	}

	//Set 개수가 10000개가 넘어가면 과거데이터를 500개씩 제거한다.
	private void removeOverCountQueue() {
		if(dynamicSet.size()>dynamicSetSize) {
//			logger.info("removeOverCountQueue!!!!("+dynamicSet.size()+")");
			int i=0;
			for( Iterator<String> itr =dynamicSet.iterator(); itr.hasNext()&&i<dynamicRemoveUnitSize; )
			{
				dynamicSet.remove(itr.next());
				i++;
			}
//			logger.info("removeOverCountQueue2!!!!("+dynamicSet.size()+")");
		}
	}
	
	

	public synchronized int getCountAndSetZero() {
		int cnt=exceptCnt;
		exceptCnt = 0;
		return cnt;
	}
	
	
	
	private void sleep(long millis) {
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
			logger.debug("[TargetManageRunnable] sleep error : "+e.getLocalizedMessage());
		}
	}

	public void setRunning(boolean isRunning) {
		this.isRunning = isRunning;
	}


	public void setMarineAreaLoader(MarineAreaLoader marineAreaLoader) {
		this.marineAreaLoader = marineAreaLoader;
	}

	
	
//	class SetVo implements Comparable<SetVo>{
//		public SetVo(String key) {
//			this.key=key;
//		}
//		String key;
//		long timeStamp = LocalDateTime.now().toInstant(ZoneOffset.ofHours(9)).toEpochMilli();
//		@Override
//		public int compareTo(SetVo o) {
//			return Integer.parseInt((this.timeStamp-o.timeStamp)+"");
//		}
//	}
	
}
