package com.eactive.eai.util.json;

import java.util.Map;

import com.eactive.eai.common.util.Logger;
import com.eactive.eai.util.json.transformer.ValueTransformer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;

public class JsonPathsTransform {
	static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
	private static final ObjectMapper objectMapper = new ObjectMapper();

	public static <T, R> String modifyValuesAtPaths(String jsonString,
			Map<String, ValueTransformer<T, R>> pathTransformerMap, boolean isPretty) {
		String path = null;

//		DocumentContext documentContext = JsonPath.parse(jsonString);

		// 변경헤도 별차이가 없음.
		Configuration conf = Configuration.builder()
			    .jsonProvider(new JacksonJsonNodeJsonProvider())
			    .mappingProvider(new JacksonMappingProvider())
			    .build();
		DocumentContext documentContext = JsonPath.using(conf).parse(jsonString);
			
		for (Map.Entry<String, ValueTransformer<T, R>> entry : pathTransformerMap.entrySet()) {
			try {
				path = entry.getKey();
				ValueTransformer<T, R> transformer = entry.getValue();

				// 현재 값 추출
				T currentValue = (T) documentContext.read(path, String.class);
				 
				// 변환기 통해 새 값 생성
				R newValue = transformer.transform(currentValue);
				// 새로운 값으로 설정
				documentContext.set(path, newValue);

				if (logger.isDebug()) {
					// FIXME : kbank - 로그내용 수정
					String encLog = transformer.getClass().getName() + " : "
							+ String.format("path=%s, orgText[%s] plain[%s] newText[%s]", path, currentValue,
									transformer.getProperty("PLAIN_VALUE"), newValue);
					// System.out.println(encLog);
					logger.debug(encLog);
				}
			} catch (Exception e) {
				logger.error("SKIP ERROR jsonpath=" + path, e);
			}
		}
		return printJson(documentContext.jsonString(), isPretty);

	}

	// JSON을 pretty하게 출력하는 메서드
	private static String printJson(String jsonString, boolean isPretty) {
		try {
			Object jsonObject = objectMapper.readValue(jsonString, Object.class);
			if (isPretty) {
				return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject);
			} else {
				return objectMapper.writeValueAsString(jsonObject);
			}
		} catch (JsonProcessingException e) {
			return jsonString;
		}
	}

}
