package org.bdware.analysis.taint;

import java.util.List;

import org.bdware.analysis.BasicBlock;
import org.bdware.analysis.CFGraph;
import org.bdware.analysis.InsnPrinter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.MethodNode;

public class TaintCFG extends CFGraph {
	public TaintBits taintBits;

	public TaintCFG(MethodNode mn) {
		super(mn);
		taintBits = new TaintBits();
	}

	@Override
	public BasicBlock getBasicBlock(int id) {
		return new TaintBB(id);
	}

	public int argsLocal() {
		String desc = getMethodNode().desc;
		String[] parameters = desc.split("[)]");
		String parameter = parameters[0];
		String[] args = parameter.split("[;]");
		return args.length - 1;
	}

	public void executeLocal() {
		for (BasicBlock bb : basicBlocks) {
			for (AbstractInsnNode an : bb.getInsn()) {
				if (an instanceof InvokeDynamicInsnNode) {
					InvokeDynamicInsnNode inDy = (InvokeDynamicInsnNode) an;
					if (inDy.name.contains("dyn:call:executeContract")) {
						taintBits.allocate(inDy.name + inDy.hashCode());
					}
				}
			}
		}
		return;
	}

	public void printSelf() {
		InsnPrinter printer = new InsnPrinter(Opcodes.ASM4, System.out);
		printer.setLabelOrder(getLabelOrder());
		System.out.println("======Method:" + getMethodNode().name + getMethodNode().desc + "=======");
		System.out.println("=====TaintInfo: " + taintBits.taintInfo() + "===========");
		for (BasicBlock bb : basicBlocks) {
			System.out.print("==B" + bb.blockID);
			if (getSucBlocks(bb).size() > 0)
				System.out.print("-->");
			for (BasicBlock suc : getSucBlocks(bb))
				System.out.print(" B" + suc.blockID);
			System.out.println("==");
			TaintBB b = (TaintBB) bb;
			if (b.preResult != null) {
				System.out.print("前序分析结果：");
				b.preResult.printResult();
			    //System.out.println("test:"+b.getResultWithTaintBit());
			}

			for (AbstractInsnNode an : bb.getInsn()) {
				an.accept(printer);
			}
		}

	}

	public TaintBB getLastBlock() {
		if (basicBlocks != null && basicBlocks.size() > 0)
			return (TaintBB) basicBlocks.get(basicBlocks.size() - 1);
		return null;
	}
	
	public List<BasicBlock> getBlocks() {
		return basicBlocks;
	}

}
