package com.eactive.eai.transformer.layout;

import java.math.BigDecimal;

import org.apache.commons.lang3.StringUtils;
import org.nfunk.jep.ParseException;

import com.eactive.eai.transformer.SystemKeys;


public class Converter {
	private Converter() {
		
	}
	public static Object convert(Object value, Item item) throws Exception {
        if (value == null) {
            return null;
        }
        
        int type = item.getDataTypeId();
        int tLen = item.getLength();
        int dLen = item.getDecimalPointLength();
        
        switch (type) {
            case Types.TYPE_UNKNOWN:
                return null;
    
            case Types.TYPE_INT:    
                if (value instanceof Double) {
            		return ((Number) value).intValue();
	            } else if (value instanceof Number) {
                    return new Integer((((Number) value)).intValue());
                } else if (value instanceof String) {
                    return new Integer(((String) value));
                } else if (value instanceof byte[]) {
                    try {
                        return new Integer(new String((byte[]) value).trim());
                    } catch(NumberFormatException e) {
                        return Integer.valueOf(0);
                    }
                } else {
                	throw new Exception("TYPE_INT 변환을 할 수 없습니다. : " + value.getClass().getName());
                }
    
            case Types.TYPE_LONG:    
                if (value instanceof Double) {
	            	if (((Double) value).doubleValue() == Math.round(((Double) value).doubleValue())) {
	            		return new Long(Math.round(((Double) value).doubleValue()));
	            	} else {
	            		return new Long((((Number) value)).longValue());
	            	}
                } else if (value instanceof Number) {
                    return new Long((((Number) value)).longValue());
                } else if (value instanceof String) {
                    return new Long(((String) value));
                } else if (value instanceof byte[]) {
                    try {
                        return new Long(new String((byte[]) value).trim());
                    } catch(NumberFormatException e) {
                        return Long.valueOf(0);
                    }
                } else {
                	throw new Exception("TYPE_LONG 변환을 할 수 없습니다. : " + value.getClass().getName());
                }
    
            case Types.TYPE_SHORT:    
                if (value instanceof Double) {
	            	if (((Double) value).doubleValue() == Math.round(((Double) value).doubleValue())) {
	            		return new Short(String.valueOf(Math.round(((Double) value).doubleValue())));
	            	} else {
	            		return new Short(String.valueOf((((Number) value)).longValue()));
	            	}
                } else if (value instanceof Number) {
                    return new Short((((Number) value)).shortValue());
                } else if (value instanceof String) {
                    return new Short(((String) value));
                } else if (value instanceof byte[]) {
                    try {
                        return new Short(new String((byte[]) value).trim());
                    } catch(NumberFormatException e) {
                        return new Short("0");
                    }
                } else {
                	throw new Exception("TYPE_SHORT 변환을 할 수 없습니다. : " + value.getClass().getName());
                }
    
            case Types.TYPE_DOUBLE:    
                if (value instanceof Number) {
                    return new Double((((Number) value)).doubleValue());
                } else if (value instanceof String) {
                    return new Double(((String) value));
                } else if (value instanceof byte[]) {
                    try {
                        return new Double(new String((byte[]) value).trim());
                    } catch(NumberFormatException e) {
                        return Double.valueOf(0);
                    }
                } else {
                	throw new Exception("TYPE_DOUBLE 변환을 할 수 없습니다. : " + value.getClass().getName());
                }
    
            case Types.TYPE_FLOAT:    
                if (value instanceof Number) {
                    return new Float(((Number) value).floatValue());
                } else if (value instanceof String) {
                    return new Float(((String) value));
                } else if (value instanceof byte[]) {
                    try {
                        return new Float(new String((byte[]) value).trim());
                    } catch(NumberFormatException e) {
                        return Float.valueOf(0);
                    }
                } else {
                	throw new Exception("TYPE_FLOAT 변환을 할 수 없습니다. : " + value.getClass().getName());
                }
    
            case Types.TYPE_BIGDECIMAL:    
                if (value instanceof Double) {
	            	if (((Double) value).doubleValue() == Math.round(((Double) value).doubleValue())) {
	            		return new BigDecimal(Math.round(((Double) value).doubleValue()));
	            	} else {
	            		// 소숫점 없애는 버그 수정
	            		// 20190829 by OHS
	            		return BigDecimal.valueOf((Double) value);
	            	}
                } else if (value instanceof Number) {
                    return new BigDecimal(((Number) value).toString());
                } else if (value instanceof String) {
                	// add point if not exist
                	String sVal = (String) value;
                	if(dLen> 0 && SystemKeys.isAddDecimalPointEnabled()) {
                		sVal = addPoint(sVal, tLen, dLen);
                	}
                    return new BigDecimal( sVal );
                } else if (value instanceof byte[]) {
                	// add point if not exist
                    try {
                    	String sVal = new String((byte[]) value).trim();
                    	if(dLen> 0 && SystemKeys.isAddDecimalPointEnabled()) {
                    		sVal = addPoint(sVal, tLen, dLen);
                    	}
                        return new BigDecimal(sVal);
                    } catch(NumberFormatException e) {
                        return new BigDecimal("0");
                    }
                } else {
                	throw new Exception("TYPE_BIGDECIMAL 변환을 할 수 없습니다. : " + value.getClass().getName());
                }
                
            case Types.TYPE_STRING: 
            	String valString = null;
            	if (value instanceof String) {
                	valString = (String) value;
                    if(SystemKeys.isStringTrimEnd()) valString = StringUtils.stripEnd(valString," ");
                } else if (value instanceof byte[]) {
                	// source 가 bytes 인 경우에는 ms949로 인코딩해야 함.
                	valString = new String((byte[]) value , SystemKeys.getBytesMessageCharset());
                    if(SystemKeys.isStringTrimEnd()) valString = StringUtils.stripEnd(valString," ");
                } else if (value instanceof Double) {
                	if (((Double) value).doubleValue() == Math.round(((Double) value).doubleValue())) {
                		valString = new Long(Math.round(((Double) value).doubleValue())).toString();
                	}
                	valString = BigDecimal.valueOf((Double) value).toString();
                } else if (value instanceof Number) {
                	valString = value.toString();
                } else if (value instanceof Boolean) {
                	valString = ((Boolean)value).toString();
                } 
                else {
                	valString = ((String) value).toString();
                }                    
                return valString;
            case Types.TYPE_BYTEARRAY:  
                if (value instanceof byte[]) {
                    return (byte[])value;
                } else if (value instanceof String) {
                	// SystemKeys.getBytesMessageCharset 으로 변경
                    return ((String) value).getBytes(SystemKeys.getBytesMessageCharset());
                } else if (value instanceof Double) {
                	if (((Double) value).doubleValue() == Math.round(((Double) value).doubleValue())) {
                		return new Long(Math.round(((Double) value).doubleValue())).toString().getBytes();
                	}
                    return BigDecimal.valueOf((Double) value).toString().getBytes();
                } else if (value instanceof Number) {
                	String val = value.toString();
                	if(dLen> 0 && SystemKeys.isAddDecimalPointEnabled()) {
                		val = StringUtils.replace( val, ".", "");                		
                	}
                	val =  StringUtils.leftPad( val, tLen, "0");
                    return val.getBytes();
                } else {
                	throw new Exception("TYPE_BYTEARRAY 변환을 할 수 없습니다. : " + value.getClass().getName());
                }
            case Types.TYPE_BOOLEAN: 
                if (value instanceof String) {
                    return Boolean.valueOf((String)value);
                } else if (value instanceof byte[]) {
                    return Boolean.valueOf( new String((byte[]) value) );
                } else if (value instanceof Boolean) {
                	return (Boolean)value;
                } else {
                	throw new Exception("TYPE_BOOLEAN 변환을 할 수 없습니다. : " + value.getClass().getName());
                }                    
                
            // USER DEFINED JAVA OBJECT
            case Types.TYPE_OBJECT:
                return value;
    
            default:
                throw new Exception("정의되지 않은 기본 값 타입을 사용합니다. -  " + type);
        }
	}
	
	public static boolean isValid(String value, int length, int pointLength) {
		String normalized = value.replaceAll(" ", "");
		if (SystemKeys.isScientificNormalizeEnabled()) {
			try {
				normalized = new BigDecimal(normalized).toPlainString();
			} catch (NumberFormatException e) {
				return false;
			}
		}
		String[] data = normalized.split("[.]");
		if (pointLength > 0) {
			if (data.length == 1) {
				if (data[0].length() > length - pointLength - 1) return false;
			} else if (data.length == 2) {
				if (data[0].length() > length - pointLength - 1) return false;
				if (data[1].length() > pointLength) return false;
			} else {
				return false;
			}
		} else {
			if (data.length != 1) return false;
			if (data[0].length() > length) return false;
		}
		return true;
	}

	public static String addPoint(String dpNum, int tLen , int dLen) {
    	if (dpNum == null || dpNum.trim().length() ==0 ){
    		return "0";
    	}
    	
    	if(dLen < 1 || dpNum.indexOf(".") > -1) {
    		return dpNum;
    	}
    	int sLen = dpNum.length();
    	int pLen = sLen - dLen;
    	
    	StringBuilder sb = new StringBuilder(sLen +1);
    	sb.append(dpNum.substring(0, pLen));
    	sb.append(".");
    	sb.append(dpNum.substring(pLen));
    	return sb.toString();
    }
}
