package com.gradle.ares

import com.gradle.MyLogger
import org.gradle.api.Project
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.FieldVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes

/**
 * Created by Glen on 2017/2/8.
 */

public class ClassAdapter extends ClassVisitor {
    private Project project;

    private int access;
    private String className;
    private String superName;
    private String[] interfaces;

    private boolean isAdAgent;
    private boolean isModifyField;
    private Set<MethodModel> addLifecycleSet = null;

    private boolean modify;

    public ClassAdapter(ClassVisitor cv, Project project) {
        super(Opcodes.ASM5, cv)
        this.project = project
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces)
        this.access = access
        this.className = name
        this.superName = superName
        this.interfaces = interfaces
        //初始化
        this.isAdAgent = AresValue.AgentClass != name && !name.contains("android/support")
        this.isModifyField = AresValue.AgentClass == name
        for (String su : MethodLifeCycleVisitor.SuperClass) {
            if (!className.contains("android/support") && su == superName ) {
                addLifecycleSet = new HashSet<>()
            }
        }
        MyLogger.info("class:" + this.className + "_" + this.superName + "_" + this.interfaces)
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions)

        if (isAdAgent) {
            def agent = MethodAgentVisitor.getAgent(this.access, this.className, this.superName, name, desc)
            if (agent != null) {
                modify = true
                MyLogger.lifecycle("agent:" + name + "_" + desc + "_from:" + this.className)
                mv = new MethodAgentVisitor(mv, agent)

            }
        }

        if (addLifecycleSet != null) {
            def agent = MethodLifeCycleVisitor.getAgent(this.access, this.className, this.superName, name, desc)
            if (agent != null) {
                modify = true
                MyLogger.lifecycle("lifecycle:modify:" + name + "_" + desc + "_from:" + this.className)
                mv = new MethodLifeCycleVisitor(mv, agent)
                addLifecycleSet.add(agent)
            }
        }
        return mv
    }

    @Override
    FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
        if (isModifyField) {
            if (AresValue.AgentPackageField == name) {
                modify = true
                MyLogger.lifecycle("field:" + name + "_" + desc + "_from:" + this.className)
                return super.visitField(access, name, desc, signature, getPackageName())
            }

            if (AresValue.AgentPluginField == name) {
                modify = true
                MyLogger.lifecycle("field:" + name + "_" + desc + "_from:" + this.className)
                return super.visitField(access, name, desc, signature, true)
            }
        }
        return super.visitField(access, name, desc, signature, value)
    }

    @Override
    void visitEnd() {
        if (addLifecycleSet != null) {
            modify = true
            MethodLifeCycleVisitor.addMethods(addLifecycleSet, this.className, this.superName, this.cv)
        }
        super.visitEnd()
    }

    public boolean getModify() {
        return modify
    }

    /**
     * 获取xml定义包名
     * @return
     */
    private String getPackageName() {
        def manifestFile = project.android.sourceSets.main.manifest.srcFile
        def packageName = new XmlParser().parse(manifestFile).attribute('package')
        return packageName
    }
}