package gmt.common.util;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class RsCodeJava {
	
	static {
//		OS 구분
		String os = System.getProperty("os.name").toLowerCase(); 
		File file = new File("");

// 		1. 윈도우 현재 패키지까지의 경로 + dll 파일 명
		String path2 = RsCodeJava.class.getResource("").getPath(); 
		System.out.println("path2 : "+path2);
		if (os.contains("win")) { 
			file = new File(path2+"RsCode.dll");
			if(file.exists()) {
				System.out.println("path2 exists true : dll");
				System.out.println(path2+"RsCode.dll");
				System.load(path2+"RsCode.dll");
			}
		} else if (os.contains("linux")) { 
			file = new File(path2+"RsCode.so");
			if(file.exists()) {
				System.out.println("path2 exists true : so");
				System.out.println(path2+"RsCode.so");
				System.load(path2+"RsCode.so");
			}
		}
		
// 		2. 리눅스 경로
		Path relativePath = Paths.get("");
		String path3 = relativePath.toAbsolutePath().toString();
		System.out.println("path3 : " + path3);
		if (os.contains("win")) {
			file = new File(path3+"\\RsCode.dll");
			if(file.exists()) {
				System.out.println("path3 exists true : dll");
				System.out.println(path3+"\\RsCode.dll");
				System.load(path3+"\\RsCode.dll");
			}
		} else if (os.contains("linux")) { 
			file = new File(path3+"/RsCode.so");
			if(file.exists()) {
				System.out.println("path3 exists true : so");
				System.out.println(path3+"/RsCode.so");
				System.load(path3+"/RsCode.so");
			}
		}
	}
	
	private native char CalculateCrcCCITT(byte[] pCrcData, int nLen);
	private native byte[] AppendRsCodeForTX(byte[] pMsgData, int nMsgLen, int nRsLen, byte[] pTxData);
	private native byte[] DecodeRsCodeForRX(byte[] pRxData,  int nTotLen, int nRsLen);
	private native int DecodeRsCodeForRXResult(byte[] pRxData,  int nTotLen, int nRsLen);
	
	public static byte[] callCRC(String inputHex) {
		RsCodeJava rsCodeDll = new RsCodeJava();
		
		// CRC 변수 선언(pCrcData = hexStr, nLen = nLen)
		byte[] pData = hexStringToByteArray(inputHex);
		byte[] pCrcBig = new byte[pData.length + 2];
		int pDataLen = pData.length;
		
		// 반환된 CRC밸류(Int, Hex)
		char crc = rsCodeDll.CalculateCrcCCITT(pData, pDataLen);
		
		// 배열 복사
		System.arraycopy(pData, 0, pCrcBig, 0, pData.length);
		pCrcBig[pCrcBig.length-1] = (byte) (crc);
		pCrcBig[pCrcBig.length-2] = (byte) (crc>>8);
		
		return pCrcBig;
	}
	
	public static byte[] callECC(byte[] input, int RsSize) {
		RsCodeJava rsCodeDll = new RsCodeJava();

		int inputSize = input.length;
		
		// 입력 Hex Length
		byte[] pTxData = new byte[inputSize+RsSize];
		byte[] eccByte = rsCodeDll.AppendRsCodeForTX(input, inputSize, RsSize, pTxData);

		return eccByte;
	}
	
	
	public static List<Object> CheckECC(byte[] input, int RsSize) {
		RsCodeJava rsCodeDll = new RsCodeJava();

		int totLen = input.length;
		int result = -1;
		byte[] decode = rsCodeDll.DecodeRsCodeForRX(input, totLen, RsSize);
		result = rsCodeDll.DecodeRsCodeForRXResult(input, totLen, RsSize);
		
		List<Object> retList = new ArrayList<Object>();
		retList.add(decode);
		retList.add(result);
		return retList;
	}
	
	// 성공실패 여부
	public static String IfThen(int i) {
		if (i == 0) {
			return "성공";
		}
		else {
			return "실패";
		}
				
	}
	
	public byte[] intToBytes(int my_int) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutput out = new ObjectOutputStream(bos);
		out.writeInt(my_int);
		out.close();
		byte[] int_bytes = bos.toByteArray();
		bos.close();
		return int_bytes;
	}
	
	public static byte[] hexStringToByteArray(String s) {
	    int len = s.length();
	    byte[] data = new byte[len / 2];
	    for (int i = 0; i < len; i += 2) {
	        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
	    }
	    return data;
	}
	
	public static String byteArrayToHexString(byte[] bytes){ 
		StringBuilder sb = new StringBuilder(); 
		for(byte b : bytes){ 
			sb.append(String.format("%02X", b&0xff)); 
		} 
		return sb.toString(); 
	} 
}

