package com.eactive.eai.custom.adapter.http.client.impl;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Properties;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;

import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
import com.eactive.eai.adapter.http.client.impl.HttpClient5AdapterServiceRest;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.MaskingUtils;

/**
 * 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를 GET/POST 방식으로 호출할 수 있는
 * 기능을 제공한다.<br>
 * 2. 처리 개요 : <br>
 * * - 2020-09-25: Http Header 받아서 처리할 수 있게 기능 추가<br>
 * 3. 주의사항 <br> 
 *
 * @author :
 * @version : v 1.0.0
 * @see : HttpClientAdapterServiceFactory.java,
 *      HttpClientAdapterServiceSupport.java
 * @since :
 *
 */
public class HttpClient5AdapterServiceBigTech extends HttpClient5AdapterServiceRest
		implements HttpClientAdapterServiceKey {
	
	private static final char[] _HEX_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
			'e', 'f' };

	private static String hexEncode(byte[] data) {

		if (data == null) {
			return null;
		}

		int length = data.length;
		char[] encoded = new char[length << 1];

		for (int i = 0, j = 0; i < length; i++) {
			encoded[j++] = _HEX_LOWER[(0xF0 & data[i]) >>> 4];
			encoded[j++] = _HEX_LOWER[0x0F & data[i]];
		}

		return new String(encoded);
	} // end of hex_encode

	private static final String _BTP_CHARSET = "UTF-8";
	private static final String _BTP_ALGORITHM = "HmacSHA256";
	private static final String _BTP_ACCESS_KEY = "{BTP_ACCESS_KEY}";
	private static final String _BTP_SECRET_KEY = "{BTP_SECRET_KEY}";

	private static byte[] mac(String charset, String algorithm, String timestamp, String accessKey, String secretKey,
			String url) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
		String message = String.join(" ", Arrays.asList(url, timestamp, accessKey));
		SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(charset), algorithm);
		Mac mac = Mac.getInstance(algorithm);
		mac.init(secretKeySpec);

		return mac.doFinal(message.getBytes(charset));
	}// end of mac

	private static String macHex(String charset, String algorithm, String timestamp, String accessKey, String secretKey,
			String url) throws InvalidKeyException, UnsupportedEncodingException, NoSuchAlgorithmException {
		return hexEncode(mac(charset, algorithm, timestamp, accessKey, secretKey, url));
	}// end of macHex
	
	protected void assignRequestHeaders(HttpUriRequestBase method, Object httpHeader, Properties prop, Properties tempProp) {
		super.assignRequestHeaders(method, httpHeader, prop, tempProp);

		try {
			String adapterGroupName = tempProp.getProperty(ADAPTER_GROUP_NAME);
			Properties customProp = PropManager.getInstance().getProperties(adapterGroupName);
			String charset = customProp.getProperty("_BTP_CHARSET", _BTP_CHARSET);
			String algorithm = customProp.getProperty("_BTP_ALGORITHM", _BTP_ALGORITHM);
			String timestamp = System.currentTimeMillis() + "";
			String accessKey = customProp.getProperty("_BTP_ACCESS_KEY", _BTP_ACCESS_KEY);
			String secretKey = customProp.getProperty("_BTP_SECRET_KEY", _BTP_SECRET_KEY);
			if(logger.isDebug()) {
				logger.debug("charset={}", charset);
				logger.debug("algorithm={}", algorithm);
				logger.debug("timestamp={}", timestamp);
				logger.debug("accessKey={}", accessKey);
				logger.debug("secretKey={}", MaskingUtils.maskPassword(secretKey));
				logger.debug("url={}", method.getRequestUri());
			}
			
			String signature = macHex(charset// charset
					, algorithm// algorithm
					, timestamp// timestamp
					, accessKey// accessKey
					, secretKey// secretKey
					, method.getRequestUri());
			
			method.setHeader("x-btp-access-key", accessKey);
			method.setHeader("x-btp-timestamp", timestamp);
			method.setHeader("x-btp-signature-v1", signature);

		} catch (InvalidKeyException | UnsupportedEncodingException | NoSuchAlgorithmException e) {
			throw new RuntimeException("BigTech 헤더 설정 실패", e);
		}
	}
	
//	public static void main(String[] args) {
//        try {
//            String url = "/rest/v1/service?param0=&param1=";
//            String timestamp = System.currentTimeMillis()+"";
//            String accessKey = _BTP_ACCESS_KEY;
//            String secretKey = _BTP_SECRET_KEY;
//            String signature = macHex(
//            	  _BTP_CHARSET//charset
//                , _BTP_ALGORITHM//algorithm
//                , timestamp// timestamp
//                , _BTP_ACCESS_KEY//accessKey
//                , _BTP_SECRET_KEY//secretKey
//                , url
//            );
//            System.out.println(String.format("charset=%s", _BTP_CHARSET));
//            System.out.println(String.format("algorithm=%s", _BTP_ALGORITHM));
//            System.out.println(String.format("accessKey=%s", accessKey));
//            System.out.println(String.format("secretKey=%s", secretKey));
//            System.out.println(String.format("timestamp=%s", timestamp));
//            System.out.println(String.format("signature=%s", signature));
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }// end of main
}
