package nlib.sch.service.impl;



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.beanutils.BeanUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;

import nlib.sch.service.NlibSearchVO;
import nlib.col.service.CollectionVO;
import nlib.restful.DataApi;
import nlib.restful.service.DataApiInterface;
import nlib.restful.service.DataApiReqVO;
import nlib.restful.service.DataApiResVO;
import nlib.restful.service.impl.DataApiRESTful;
import nlib.sch.service.NlibSearchCollectionVO;
import nlib.sch.service.NlibSearchInterface;
import nlib.sch.service.NlibSearchService;
import nlib.util.StringUtil;


@Service("nlibSearchService")
public class NlibSearchServiceImpl implements NlibSearchService{

	private static final Logger log = LoggerFactory.getLogger(NlibSearchServiceImpl.class);
	
	/* DataApi 접속 서버 정보 */ 
	@Value("#{properties['search.searchIp']}") 
	private String SEARCH_IP;
	
	@Value("#{properties['search.searchPort']}") 
	private String SEARCH_PORT;
	
	@Value("#{properties['search.protocol']}") 
	private String SEARCH_PROTOCOL;
	
	/** RESTFul API 송수신 모듈 */
	@Resource(name = "dataApi")
	private DataApi dataApi;
	
	public NlibSearchVO getSearch(NlibSearchVO searchVO) throws Exception {
		try {
			//검색엔진 페이지 셋팅
			searchVO.setListCount(Integer.toString(searchVO.getPageSize()));
			searchVO.setStartCount(Integer.toString(searchVO.getPageIndex()));
			
			
			String collectionTemp="";
			String nameTemp="";
        	//-----------------------------------
    		// 입력값 검증작업 
        	//-----------------------------------
    		/*resVO = DataApiInterface.checkReqCommonParams(reqVO);
        	if(resVO != null) return resVO;
        	HttpMethod method = reqVO.getReqMethod();*/
    	
        	//-----------------------------------
        	// 폼 파라메터 생성 작업 및 요청 처리 
        	//-----------------------------------
    		String url = SEARCH_PROTOCOL + "://" + SEARCH_IP + ("80".equals(SEARCH_PORT) ? "" : ":" + SEARCH_PORT) + "/searchApi/searchApi.jsp";
    		log.debug("REQ URL : " + url);

    		HttpHeaders headers = new HttpHeaders();
    		headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    		
    		ResponseEntity<String> responseEntity = null;
    		ResponseEntity<String> allResponseEntity = null;
    		RestTemplate restTemplate = new RestTemplate();
    		restTemplate.getMessageConverters()
    			.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
    		
    		//단일 탭 검색
    		MultiValueMap<String, String> parameters= searchVO.getSearchMap();
    		
    		//전체 검색 (각 탭별 count가 목적)
    		collectionTemp = searchVO.getCollection();
    		if("".equals(StringUtil.getString(searchVO.getCollectionList(), "")) || "ALL".equals(StringUtil.getString(searchVO.getCollectionList(), "")))
    		{
    			searchVO.setCollection("ALL");
    		}else 
    		{
    			//상세검색시 콜렉션리스트만 카운트하기위해 추가.
    			searchVO.setCollection(searchVO.getCollectionList());
    		}
    		
    		MultiValueMap<String, String> allParameters= searchVO.getSearchMap();
    		searchVO.setCollection(collectionTemp);
    		//post방식
    		parameters.forEach((k, v) -> log.debug("params > " + k + " : " + v));
    		allParameters.forEach((k, v) -> log.debug("allParams > " + k + " : " + v));
    		HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity(parameters, headers);
    		HttpEntity<MultiValueMap<String, String>> allRequestEntity = new HttpEntity(allParameters, headers);
    		responseEntity = restTemplate.postForEntity(url, requestEntity , String.class);
    		allResponseEntity = restTemplate.postForEntity(url, allRequestEntity , String.class);
    		
        	//-----------------------------------
        	// 응답 처리  
        	//-----------------------------------
    	    HttpStatus statusCode = responseEntity.getStatusCode();
    		log.debug("RES StatusCode : " + statusCode);
    	    String resultXML = responseEntity.getBody();
    	    log.debug("RES resultXML : " + resultXML);
    	    
    	    HttpStatus allStatusCode = allResponseEntity.getStatusCode();
    	    log.debug("RES allStatusCode : " + allStatusCode);
    	    String allResultXML = allResponseEntity.getBody();
    	    log.debug("RES allResultXML : " + allResultXML);

    	    //검색엔진 결과 json 파싱
    	    JsonParser jsonParser = new JsonParser();
    	    
    	    
    	    JsonObject jsonObject = null;
     	    JsonObject tmp = null;
    	    String collection = "";
    	    String totalCount = "";
    	    JsonArray jsonArray = null;
    	    
    	    //전체검색 결과 탭별 count
    	    jsonObject = (JsonObject) jsonParser.parse(allResultXML);
    	    jsonObject = (JsonObject) jsonObject.get("SearchQueryResult");
    	    jsonArray = (JsonArray) jsonObject.get("Collection");
    	    
    	    for(int i=0;i<jsonArray.size();i++){
    	    	tmp = (JsonObject)jsonArray.get(i);
    	    	
    	    	//각 탭별 총개수
    	    	collection = tmp.get("Id").getAsString();
    	    	tmp = (JsonObject) tmp.get("DocumentSet");
    	    	totalCount = tmp.get("TotalCount").getAsString();
    	    	
    	    	searchVO.setCollectionTotalCount(collection, totalCount);
    	    };
    		
    	    //단일 탭 결과데이터 담기
    	    JsonArray colArray = null;
    	    jsonObject = (JsonObject) jsonParser.parse(resultXML);
    	    jsonObject = (JsonObject) jsonObject.get("SearchQueryResult");
    	    jsonArray = (JsonArray) jsonObject.get("Collection");
    	    JsonObject filterObject = null; 
    	    JsonArray filterList = null; 
    	    JsonArray tmpList = null; 
    	    JsonArray subjectList = null; 
    	    JsonArray typeList = null; 
    	    JsonArray orgList = null; 
    	    JsonArray categoryList = null; 
    	    List<CollectionVO> list = new ArrayList<>();
    	    List<HashMap<String,String>> subjectMap = new ArrayList<HashMap<String,String>>();
    	    List<HashMap<String,String>> typeMap = new ArrayList<HashMap<String,String>>();
    	    List<HashMap<String,String>> orgMap = new ArrayList<HashMap<String,String>>();
    	    String code="";
    	    String code_up="";
    	    int j;
    	    int k;
    	    
    	    for(int i=0;i<jsonArray.size();i++){
    	    	tmp = (JsonObject)jsonArray.get(i);
    	    	if(searchVO.getCollection().equals(tmp.get("Id").getAsString()))
    	    	{
    	    		//주제분야 , 자료유형 ,생산기관 별 카운트
    	    		tmpList = (JsonArray) tmp.get("CategoryGroup");
    	    		if(tmpList != null)
    	    		{
	    	    		for( k=0; k < tmpList.size(); k++){
	    	    			filterObject = (JsonObject) tmpList.get(k);
	    	    			
	    	    			if(filterObject.get("SUBJECT_CATE") != null)
	        	    		{
	    	    				subjectList = (JsonArray) filterObject.get("SUBJECT_CATE");
	        	    		}
	        	    		if(filterObject.get("DIV_CATE") != null)
	        	    		{
	        	    			typeList = (JsonArray) filterObject.get("DIV_CATE");
	        	    		}
	        	    		if(filterObject.get("ORG_NM") != null)
	        	    		{
	        	    			orgList = (JsonArray) filterObject.get("ORG_NM");
	        	    		}
	    	    		}
	    	    		if(subjectList.size()>0) 
	    	    		{
	    	    			filterObject =(JsonObject) subjectList.get(0);
	    					filterObject = (JsonObject) filterObject.get("Categories");
	        	    		subjectList = (JsonArray) filterObject.get("Category");
	    	    		}; 
	    	    		if(typeList.size()>0) 
	    	    		{
		    	    		filterObject =(JsonObject) typeList.get(0);
		    	    		filterObject = (JsonObject) filterObject.get("Categories");
		    	    		typeList = (JsonArray) filterObject.get("Category");
	    	    		}; 
	    	    		if(orgList.size()>0) 
	    	    		{
		    	    		filterObject =(JsonObject) orgList.get(0);
		    	    		filterObject = (JsonObject) filterObject.get("Categories");
		    	    		orgList = (JsonArray) filterObject.get("Category");
	    	    		};
	    	    		for(k = 0; k < subjectList.size(); k++){
	    	    			HashMap<String,String> temp = new HashMap<String,String>();
	    	    			filterObject = (JsonObject)subjectList.get(k);
	    	    			nameTemp = filterObject.get("Name").getAsString();
	    	    			//상위코드값
	    	    			code_up = nameTemp.substring(nameTemp.indexOf("@")+1,nameTemp.indexOf("^"));
	    	    			temp.put("category_nm_up",code_up);
	    	    			
	    	    			//코드값
	    	    			code = nameTemp.substring(nameTemp.lastIndexOf("@")+1);
	    	    			temp.put("category_nm",code);
	    	    			temp.put("category_cnt",filterObject.get("Count").getAsString());
	    	    			subjectMap.add(temp);
	    	    		}
	    	    		for(k = 0; k < typeList.size(); k++){
	    	    			HashMap<String,String> temp = new HashMap<String,String>();
	    	    			filterObject = (JsonObject)typeList.get(k);
	    	    			nameTemp = filterObject.get("Name").getAsString();
	    	    			//상위코드값
	    	    			code_up = nameTemp.substring(nameTemp.indexOf("@")+1,nameTemp.indexOf("^"));
	    	    			temp.put("class_nm_up",code_up);
	    	    			
	    	    			//코드값
	    	    			code = nameTemp.substring(nameTemp.lastIndexOf("@")+1);
	    	    			temp.put("class_nm",code);
	    	    			temp.put("class_cnt",filterObject.get("Count").getAsString());
	    	    			typeMap.add(temp);
	    	    		}
	    	    		for(k = 0; k < orgList.size(); k++){
	    	    			HashMap<String,String> temp = new HashMap<String,String>();
	    	    			filterObject = (JsonObject)orgList.get(k);
	    	    			nameTemp = filterObject.get("Name").getAsString();
	    	    			if(!"null".equals(nameTemp)) {
		    	    			temp.put("org_nm",nameTemp);
		    	    			temp.put("org_cnt",filterObject.get("Count").getAsString());
		    	    			orgMap.add(temp);
	    	    			}
	    	    		}
    	    		}
    	    		
    	    		tmp = (JsonObject) tmp.get("DocumentSet");
    	    		searchVO.setTotalCount(tmp.get("TotalCount").getAsString());
    	    		colArray = (JsonArray) tmp.get("Document");
    	    		
    	    		if(colArray != null)
    	    		{
	    	    		//vo list로 json list 파싱
	    	    		for(j=0;j<colArray.size();j++){
	    	    			tmp = (JsonObject)colArray.get(j);
	    	    			tmp = (JsonObject) tmp.get("Field");
	    	    			
	    	    			CollectionVO vo = new CollectionVO();
	    	    			vo.setMasterId(tmp.get("MASTER_ID").getAsString());
	    	    			
	    	    			
	    	    			list.add(vo);
	    	    			
	    	    			/*vo = gson.fromJson(tmp, NlibSearchCollectionVO.class);*/
	    	    		/*	NlibSearchCollectionVO vo = new NlibSearchCollectionVO();
	    	    			vo.setMasterId(tmp.get); = gson.fromJson(tmp, NlibSearchCollectionVO.class);*/
	    	    		}
    	    		}
    	    	}
    	    };
    	    searchVO.setResultList(list);
    	    searchVO.setSubjectCountList(subjectMap);
    	    searchVO.setTypeCountList(typeMap);
    	    searchVO.setOrgCountList(orgMap);
    	} catch(Exception e) {
    		e.printStackTrace();
    		log.error("getSearch > Exception 발생 : " + e.toString());
    	}
		return searchVO;
	}
}

