package ca.uwaterloo.cs858.FindCrypto

import com.ibm.wala.classLoader.IMethod
import com.ibm.wala.ssa.IR
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction
import com.ibm.wala.util.graph.Graph
import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph
import com.ibm.wala.viz.DotUtil
import java.io.File

class AnalysisUtil {
    companion object {
        fun getMethodReturnSeedVN(ir: IR, method: IMethod): Int {
            for (inst in ir.iterateAllInstructions()) {
                if (inst is SSAAbstractInvokeInstruction) {
                    if (inst.callSite.declaredTarget.name == method.name) {
                        return inst.getReturnValue(0)
                    }
                }
            }

            return -100
        }

        fun getParamSeedVN(ir: IR, param: Int): Int {
            return try {
                ir.getParameter(param)
            } catch (e: java.lang.IllegalArgumentException) {
                -100
            }
        }

        fun writeWitness(source: IMethod, path: List<IMethod>, outputDir: String) {
            val witness = SlowSparseNumberedGraph.make<IMethod>()
            witness.addNode(source)
            var prev: IMethod? = source
            for (part in path.reversed()) {
                witness.addNode(part)
                if (prev != null) {
                    witness.addEdge(prev, part)
                }
                prev = part
            }

            DotUtil.dotify(witness, { method ->
                val builder = StringBuilder()
                builder.append(method.declaringClass.name.toString())
                builder.append("\n")
                builder.append(method.name.toString())
                builder.append("\n")
                builder.append(method.selector.toString())
                builder.toString()
            }, outputDir + File.separator + "witness.dot", null, null)
        }

        fun writeGraph(graph: Graph<IMethod>, outputDir: String) {
            DotUtil.dotify(graph, { method ->
                val builder = StringBuilder()
                builder.append(method.declaringClass.name.toString())
                builder.append("\n")
                builder.append(method.name.toString())
                builder.append("\n")
                builder.append(method.selector.toString())
                builder.toString()
            }, outputDir + File.separator + "graph.dot", null, null)
        }
    }
}