package kr.gmtc.gw.asderecv.rest;

import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
// import com.google.common.util.concurrent.RateLimiter;

import kr.gmtc.gw.asderecv.rest.vo.SacpServiceVO;
import kr.gmtc.gw.asderecv.rest.vo.ServiceAsdeData;
import kr.gmtc.gw.asderecv.utils.CmmnUtil;
import kr.gmtc.gw.asderecv.rest.vo.SacpServiceHeader;


@RestController
public class AsdeServiceController{

	// 프레임 워크 구성요소 //
	/** 서비스 설정, {@code application.yml} */
	// @Resource(name = "ServiceConfig")
	// private ServiceConfig serviceConfig;
	
	/* UDP test 소켓 */
	//UDPEchoClient UDPSocket ;
	
	@Resource(name = "serviceQueue")
	HashMap<Integer, Queue<ServiceAsdeData>> serviceQueue;

	@Resource(name = "packetQ")
	Queue<String> packetQ;


	Queue<ServiceAsdeData> testMap = new LinkedBlockingQueue<ServiceAsdeData>();

	/* 서비스중인지 확인 */
	@Resource(name = "serviceRunnig")
	private boolean serviceRunnig = false;
	
	@Value("${asde.service.queueCount}")
	private Integer scvQcount;

	@Value("${asde.service.serviceCount}")
	private Integer scvDatacount;

	private SacpServiceVO asdeServiceVO;

	protected Logger logger;

	protected ObjectMapper mapper;

	DateTimeFormatter dfPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

	public AsdeServiceController() {

		logger = LoggerFactory.getLogger(this.getClass());
		mapper = new ObjectMapper();
  	}
	
	@GetMapping(value = "/getASDE/{qid}", produces = MediaType.APPLICATION_JSON_VALUE)
	public synchronized ResponseEntity<String> getASDE( @PathVariable Integer qid) {

		int qidx = qid -1;

		String sRetJsonData = "";

		// synchronized(serviceQueue.get(qidx)){
			sRetJsonData = makeServiceData(qidx, serviceQueue.get(qidx));
		// }
 
		return ResponseEntity.ok(sRetJsonData);
		
	}

	@GetMapping(value = "/getQueCount/{qid}", produces = MediaType.APPLICATION_JSON_VALUE)
	public synchronized ResponseEntity<String> getQueCount( @PathVariable Integer qid) {

		int qidx = qid -1;

		String sRetJsonData = "Que Count : ";

		if(qidx == -1){
			sRetJsonData = sRetJsonData + "[" ;

			for(int idx =0;idx<serviceQueue.size();idx++){
				sRetJsonData = sRetJsonData + serviceQueue.get(idx).size() + "/" ;
			}

			sRetJsonData = sRetJsonData + " Que Size:" +serviceQueue.size()+ "]";
		}else{
			sRetJsonData = sRetJsonData + "[" + qid + "]" + serviceQueue.get(qidx).size() ;
		}

		return ResponseEntity.ok(sRetJsonData);
		
	}

	@GetMapping(value = "/getASDE/{qid}/{clsgn}", produces = MediaType.APPLICATION_JSON_VALUE)
	public ResponseEntity<String> getASDEFilter( @PathVariable Integer qid, @PathVariable String clsgn) {

		int qidx = qid -1;

		String sRetJsonData = "";

		synchronized(serviceQueue.get(qidx)){
			sRetJsonData = makeServiceDataFilter(qidx, serviceQueue.get(qidx), clsgn);
		}

		return ResponseEntity.ok(sRetJsonData);
		
	}


	private String makeServiceData(int queIdx, Queue<ServiceAsdeData> procQue){

		String sendCode, sendMsg ;
		SacpServiceHeader jsonHeader = new SacpServiceHeader();
		List<ServiceAsdeData> jsonData = new LinkedList<ServiceAsdeData>();
		
		sendCode = "200";
		sendMsg = "";
		
		asdeServiceVO = new SacpServiceVO();
		
		int qTotalSize = procQue.size();
		int qSize = qTotalSize;

		if(qSize > scvDatacount) qSize = scvDatacount;

		if(queIdx > scvQcount -1 || queIdx < 0) {
			sendCode = "Err-01";
			sendMsg = "할당되지 않은 큐를 지정했습니다.";
			logger.error(sendMsg);
		}else {
			//if(procQue.peek() == null) {
			if(qSize <= 0) {
				sendCode = "200";
				sendMsg = "전송할 데이터 없음.";
				// logger.error("procQue size" + " / " + procQue.size());
			}else{

				serviceRunnig = true;

				while (qSize > 0 ) {

					
					ServiceAsdeData data = procQue.poll();
					
					if( data != null){
						jsonData.add(data);
					}
					
					qSize--;
				}

				serviceRunnig = false ;
			}
			
		}
		
		jsonHeader.setResult_code(sendCode);
		jsonHeader.setResult_msg(sendMsg);
		
		asdeServiceVO.setHeader(jsonHeader);
		
		if (sendCode.equals("200")) {
			
			asdeServiceVO.setData(jsonData);

			int iJsonSize = jsonData.size();
			if(iJsonSize <= 0 ){
				iJsonSize = 0;
				logger.info("Que["+(queIdx + 1)+"] service count :" + jsonData.size() + "/" + qTotalSize + "/" + "[분석중:"+packetQ.size()+"]");
			}else{
				iJsonSize = iJsonSize -1;
				logger.info("Que["+(queIdx + 1)+"] service count :" + jsonData.size() + "/" + qTotalSize + "/" + "[Max-Tm:"+jsonData.get(iJsonSize).getRecptn_dt() +", Min-Tm:"+ jsonData.get(0).getRecptn_dt() + ", 분석중:"+packetQ.size()+"]");
			}

		 	
		}
		
		String sRetJsonData = "";

		try {
			sRetJsonData = mapper.writeValueAsString(asdeServiceVO);
		} catch (JsonProcessingException e) {
			logger.error("[AsdeServiceController] makeServiceData-JsonProcessingException : " + CmmnUtil.getStatckTrace(e));
		}

		return sRetJsonData;

	}

	private String makeServiceDataFilter(int queIdx, Queue<ServiceAsdeData> procQue, String... filter){

		String sendCode, sendMsg ;
		SacpServiceHeader jsonHeader = new SacpServiceHeader();
		List<ServiceAsdeData> jsonData = new LinkedList<ServiceAsdeData>();
		
		sendCode = "200";
		sendMsg = "";
		
		asdeServiceVO = new SacpServiceVO();
		
		int qTotalSize = procQue.size();
		int qSize = qTotalSize;

		if(qSize > scvDatacount) qSize = scvDatacount;

		if(queIdx > scvQcount -1 || queIdx < 0) {
			sendCode = "Err-01";
			sendMsg = "할당되지 않은 큐를 지정했습니다.";
			logger.error(sendMsg);
		}else {
			//if(procQue.peek() == null) {
			if(qSize <= 0) {
				sendCode = "200";
				sendMsg = "전송할 데이터 없음.";
				// logger.error("procQue size" + " / " + procQue.size());
			}else{

				serviceRunnig = true;
				boolean bFilter = false;

				while (qSize > 0 ) {

					ServiceAsdeData data = procQue.poll();
					
					if( data != null){
						
						if(filter[0].equals(data.getClsgn())){
							bFilter = true;
						}else{bFilter = false;}

						if(bFilter)
							jsonData.add(data);
					}
					
					qSize--;
				}

				serviceRunnig = false ;
			}
			
		}
		
		jsonHeader.setResult_code(sendCode);
		jsonHeader.setResult_msg(sendMsg);
		
		asdeServiceVO.setHeader(jsonHeader);
		
		if (sendCode.equals("200")) {
			
			asdeServiceVO.setData(jsonData);

			int iJsonSize = jsonData.size();
			if(iJsonSize <= 0 ){
				iJsonSize = 0;
				logger.info("Que["+(queIdx + 1)+"] service count :" + iJsonSize + "/" + qTotalSize + "/" + "[분석중:"+packetQ.size()+"]");
			}else{
				iJsonSize = iJsonSize -1;
				logger.info("Que["+(queIdx + 1)+"] service count :" + iJsonSize + "/" + qTotalSize + "/" + "[Max-Tm:"+jsonData.get(iJsonSize).getRecptn_dt() +", Min-Tm:"+ jsonData.get(0).getRecptn_dt() + ", 분석중:"+packetQ.size()+"]");
			}

		 	
		}
		
		String sRetJsonData = "";

		try {
			sRetJsonData = mapper.writeValueAsString(asdeServiceVO);
		} catch (JsonProcessingException e) {
			logger.error("[AsdeServiceController] makeServiceData-JsonProcessingException : " + CmmnUtil.getStatckTrace(e));
		}

		return sRetJsonData;

	}




}


