package org.bdware.sc.compiler;

import org.objectweb.asm.*;

import java.io.IOException;
import java.io.InputStream;

public class PermissionStubGenerator extends ClassVisitor implements Opcodes {
    private final String p;

    public PermissionStubGenerator(int api, ClassVisitor cn, String permission) {
        super(api, cn);
        this.p = permission;
    }

    public static byte[] generateStub(Class<?> clz, String permission) {
        PermissionStub stub = clz.getAnnotation(PermissionStub.class);
        if (stub == null)
            return null;
        try {
            String resource = clz.getCanonicalName().replaceAll("\\.", "/") + ".class";
            InputStream input = clz.getClassLoader().getResourceAsStream(resource);
            ClassReader cr;
            cr = new ClassReader(input);
            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
            PermissionStubGenerator generator = new PermissionStubGenerator(ASM4, cw, permission);
            cr.accept(generator, 0);

            return cw.toByteArray();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        if (cv != null) {
            cv.visit(version, access, name + "Stub", null, "java/lang/Object", null);
        }
        MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
        mv.visitInsn(RETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        // mv.visitLocalVariable("this", "Lcom/yancloud/sc/boundry/utils/FileUtilStub;",
        // null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        if (cv != null) {
            if (name.equals("<clinit>"))
                return null;
            if (name.equals("<init>")) {
                return null;
            }

            MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
                    new String[]{"javax/script/ScriptException"});
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitTypeInsn(NEW, "javax/script/ScriptException");
            mv.visitInsn(DUP);
            mv.visitLdcInsn("Do not have " + p + " Permission");
            mv.visitMethodInsn(INVOKESPECIAL, "javax/script/ScriptException", "<init>", "(Ljava/lang/String;)V");
            mv.visitInsn(ATHROW);
            mv.visitMaxs(5, 20);
            mv.visitEnd();

            return null;
        }
        return null;
    }
}
