package jp.igapyon.jcfa.util;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantFieldref;
import org.apache.bcel.classfile.ConstantMethodref;
import org.apache.bcel.classfile.ConstantNameAndType;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ConstantString;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.JavaClass;

public class JcfaUtil {
	private JcfaUtil() {
	}

	public static short byte2UnsignedByte(final byte byte1) {
		short word = byte1;
		if (word < 0) {
			word += 0x100;
		}
		return word;
	}

	public static int byte2UnsignedShort(final byte byte1, final byte byte2) {
		short word1 = byte1;
		short word2 = byte2;
		if (word1 < 0) {
			word1 += 0x100;
		}
		if (word2 < 0) {
			word2 += 0x100;
		}
		return word1 * 0x100 + word2;
	}

	public static int byte2Int(final byte byte1, final byte byte2,
			final byte byte3, final byte byte4) throws IOException {
		return new DataInputStream(new ByteArrayInputStream(new byte[] { byte1,
				byte2, byte3, byte4 })).readInt();
	}

	public static String getConstantString(final JavaClass jc,
			final byte operand) {
		final ConstantPool cp = jc.getConstantPool();
		final ConstantString constRef = (ConstantString) cp.getConstant(
				JcfaUtil.byte2UnsignedByte(operand), Constants.CONSTANT_String);
		return constRef.getBytes(cp);
	}

	public static String getConstantFieldrefString(final JavaClass jc,
			final byte byte1, final byte byte2) {
		final ConstantPool cp = jc.getConstantPool();
		final ConstantFieldref constRef = (ConstantFieldref) cp.getConstant(
				JcfaUtil.byte2UnsignedShort(byte1, byte2),
				Constants.CONSTANT_Fieldref);
		final ConstantNameAndType constNameAndTypeUtf8 = (ConstantNameAndType) cp
				.getConstant(constRef.getNameAndTypeIndex(),
						Constants.CONSTANT_NameAndType);
		return constRef.getClass(cp) + "#" + constNameAndTypeUtf8.getName(cp)
				+ " type:" + constNameAndTypeUtf8.getSignature(cp);
	}

	public static String getConstantMethodRefString(final JavaClass jc,
			final int operand) {
		final ConstantPool cp = jc.getConstantPool();
		final ConstantMethodref constRef = (ConstantMethodref) cp.getConstant(
				operand, Constants.CONSTANT_Methodref);
		final ConstantClass constClass = (ConstantClass) cp.getConstant(
				constRef.getClassIndex(), Constants.CONSTANT_Class);
		final ConstantUtf8 constClassUtf8 = (ConstantUtf8) cp.getConstant(
				constClass.getNameIndex(), Constants.CONSTANT_Utf8);
		final ConstantNameAndType constNameAndTypeUtf8 = (ConstantNameAndType) cp
				.getConstant(constRef.getNameAndTypeIndex(),
						Constants.CONSTANT_NameAndType);

		return (constClassUtf8.getBytes() + "#"
				+ constNameAndTypeUtf8.getName(cp) + constNameAndTypeUtf8
					.getSignature(cp));
	}
}
