package com.eactive.eai.transformer.message; 

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;

import org.apache.commons.lang3.StringUtils;

import com.eactive.eai.transformer.function.util.CodeConversion;
import com.eactive.eai.transformer.layout.Item;
import com.eactive.eai.transformer.layout.LayoutTypeKey;
import com.eactive.eai.transformer.util.ByteUtil;
import com.eactive.eai.transformer.util.CommonLib;
import com.eactive.eai.transformer.util.Constants;

public class EbcdicMessage extends BytesMessage 
{ 
	private static final long serialVersionUID = -8956817973542228440L;
	public static final String NAME = LayoutTypeKey.EBCDIC;
    
    public EbcdicMessage() {
        super();
    }    
    
    /**
     * RefOcc 에 사용됨
     */
    @Override
    public int getInt(String itemPath) { 	
        try {
            Item item = getItem(itemPath, true);

            if (item == null) {
                throw new InvalidAccessException("레이아웃항목이 존재하지 않음", itemPath);
            }

            Object value = item.getValue();
            if (value == null) {
                return 0;
            } else if (value instanceof byte[]) {
            	byte[] ascii = CodeConversion.seToAsc((byte[]) value);
				return Integer.parseInt(new String(ascii).trim());
            } else {
                throw new InvalidAccessException("레이아웃항목의 값이 숫자가 아님", itemPath);
            }
        } catch (Exception e) {
            throw new InvalidAccessException(e.getMessage(), itemPath, this, e);
        }
    }    
    
    @Override
    public void setInt(String itemPath, int value) {
    	int newValue =  value; 
        super.setInt(itemPath, newValue);
        
        Item item = getOrCreateItem(itemPath, true);
        try {
        	setBytes(itemPath, CodeConversion.ascToSE(StringUtils.leftPad(String.valueOf(value), item.getLength(), "0").getBytes()));
        } catch(Exception e) {
        	throw new MessageException(e.getMessage(), e);
        }
    }
    
    @Override
    public void setDefaultByteArray(String itemPath, byte[] value) {
        // EBCDIC일 경우 기본값설정은 ASCII로 등록하므로, EBCDIC으로 변경하도록 처리한다.
        byte[] ebcdic = null;
        try {
        	ebcdic = CodeConversion.ascToSE(value);
        	setBytes(itemPath, ebcdic);
        } catch(Exception e) {
        	throw new MessageException(e.getMessage(), e);
        }
    }
    
    @Override
    public String toString() {
        // if staled -> reorganize data
        try {
            getData();
        } catch (InvalidDataTypeException e) {
            logger.error("EbcdicMessage | " + e.getMessage(), e);
        }

        StringBuilder sb = new StringBuilder();
        sb.append(getName() + " (EbcdicMessage)");
        sb.append(super.toString());
        if (data != null) {
            sb.append("\n" + Constants.TAB + " | data = " + CommonLib.ebcdicHexDumpTab(data));
        }
        sb.append("\n" + Constants.TAB + " +--------------------------------------------------------------------------------------------------+");

        return sb.toString();
    }
    
    // EBCDIC 일 경우 0x40으로 패딩
    @Override
    public Object getData() throws InvalidDataTypeException {
        if (bStaled) {
            try {
                data = toByteArray();
            } catch(Exception e) {
                throw new InvalidDataTypeException(e.getMessage(),"EbcdicMessage.getData() method", e);   
            }
            bStaled = false;
        }

        return getDataBytes();
    }
    
    @Override
    protected byte[] toByteArray() {
    	try (
    		ByteArrayOutputStream bos = new ByteArrayOutputStream();
    	){
			for (Iterator iter = iterator(); iter.hasNext();) {
				Item item = (Item) iter.next();
				
				/**
				 * index == -1 인 경우는 무시한다
				 */
				if (item == null || item.getIndex() == -1) {
					continue;
				}
	
		        if(item.getNodeTypeId() == NODE_FIELD) {
				    if (item.getValue() == null) {		            	
		            	bos.write( ByteUtil.padding(new byte[0], item.getLength(), (byte)0x40) );
		            } else if (item.getValue() instanceof String) {
		            	bos.write( ByteUtil.padding((String) item.getValue(), item.getLength(), (byte)0x40) );
		            } else if (item.getValue() instanceof Number) {
		            	bos.write( ByteUtil.padding(((Number) item.getValue()).toString(), item.getLength(), (byte)0x40) );
		            } else {
		            	bos.write( ByteUtil.padding((byte[]) item.getValue(), item.getLength(), (byte)0x40) );
		            }	            
				}
			}
			return  bos.toByteArray();			 
    	} catch(Exception e) {
    		logger.error("retrun zero-bytes.", e);
    		return new byte[0];
    	}
    }
} 
