package com.eactive.eai.transformer.function.crypto;

import java.util.Stack;

import org.nfunk.jep.ParseException;
import org.nfunk.jep.function.PostfixMathCommand;


public class Encrypt extends PostfixMathCommand {
    public Encrypt() {
        numberOfParameters = 3;
    }

    public void run(Stack inStack) throws ParseException {
        checkStack(inStack);

        Object text = inStack.pop();
        Object bus  = inStack.pop();
        Object algo = inStack.pop();
        
        /**
         * check algorithm
         */
        if (!(algo instanceof String)) {
        	throw new ParseException("1st parameter (algorithm) must be String data type");
        } else if (!((String) algo).matches("(des|DES|des3|DES3|seed|SEED)")) {
        	throw new ParseException("1st parameter (algorithm) must be one of (DES|DES3|SEED)");
        }
        
        /**
         * check business
         */
        if (!(bus instanceof String))
        	throw new ParseException("2nd parameter (algorithm) must be String data type");

        /**
         * convert text to byte[]
         */
        byte[] value = convertToBytes(text);
        if (value == null) {
            inStack.push(null);
            return;
        }

        /**
         * encrypt
         */
        try {
        	if (((String) algo).matches("(des|DES)")) {
	        	byte[] keyData = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
	            inStack.push(new DesCodec(keyData).encrypt(value));
        	} else if (((String) algo).matches("(des3|DES3)")) {
               	byte[] keyData = {
            			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
            			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
            			0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
            		};
                inStack.push(new Des3Codec(keyData).encrypt(value));
        	} else if (((String) algo).matches("(seed|SEED)")) {
                inStack.push(new SeedCodec().encrypt(value));
        	} else {
                throw new ParseException("1st parameter (algorithm) must be one of (DES|DES3|SEED)");
        	}
        } catch (Exception e) {
            //throw new ExecutionException(e.getMessage(), parameters, e);
            throw new ParseException(e.getMessage(), e);
        }    	
    }    
    
    private byte[] convertToBytes(Object text) throws ParseException {
        byte[] value = null;

        if (text instanceof String) {
            value = ((String) text).getBytes();
        } else if (text instanceof byte[]) {
            value = (byte[]) text;
        } else if (text instanceof Double) {
        	if (((Double) text).doubleValue() == Math.round(((Double) text).doubleValue())) {
        		value = new Long(Math.round(((Double) text).doubleValue())).toString().getBytes();
        	} else {
                value =((Number) text).toString().getBytes();
        	}
        } else if (text instanceof Number) {
            value = ((Number) text).toString().getBytes();
        } else if (text == null) {
        	value = null;
        } else {
            throw new ParseException("Function의 파라미터 인수가 byte[] 또는 String이 아닙니다. : " + text);
        }
        
        return value;
    }   
}