/*
 * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.lang.instrument.*;
import java.security.ProtectionDomain;
import java.io.*;
import asmlib.*;

import static java.lang.constant.ConstantDescs.CD_int;
import static java.lang.constant.ConstantDescs.CD_void;

class RetransformAgent {

    static ClassFileTransformer t1, t2, t3, t4;
    static Instrumentation inst;
    static boolean succeeded = true;
    static int markCount = 0;
    static int[] markGolden = {30, 40, 20, 30, 40, 20, 30, 40, 20, 30, 40, 20,
                               11, 40, 20, 11, 40, 20, 11, 40, 20, 11, 40, 20};

    static class Tr implements ClassFileTransformer {
        private static final ClassDesc CD_RetransformAgent = RetransformAgent.class.describeConstable().orElseThrow();
        private static final MethodTypeDesc MTD_void_int = MethodTypeDesc.of(CD_void, CD_int);
        final String trname;
        final boolean onLoad;
        final int loadIndex;
        final boolean onRedef;
        final int redefIndex;
        final String cname;
        final String nname;

        Tr(String trname, boolean onLoad, int loadIndex, boolean onRedef, int redefIndex,
           String cname, String nname) {
            this.trname = trname;
            this.onLoad = onLoad;
            this.loadIndex = loadIndex;
            this.onRedef = onRedef;
            this.redefIndex = redefIndex;
            this.cname = cname;
            this.nname = nname;
        }

        public byte[] transform(Module module,
                                ClassLoader loader,
                                String className,
                                Class<?> classBeingRedefined,
                                ProtectionDomain    protectionDomain,
                                byte[] classfileBuffer) {
            boolean redef = classBeingRedefined != null;

            // System.err.println("hook " + trname + ": " + className +
            //                    (redef? " REDEF" : " LOAD"));
            if ((redef? onRedef : onLoad) && className != null && className.equals(cname)) {
                int fixedIndex = redef ? redefIndex : loadIndex;
                try {
                    byte[] newcf = Instrumentor.instrFor(classfileBuffer)
                                   .addMethodEntryInjection(
                                        nname,
                                        cb -> {
                                           cb.loadConstant(fixedIndex);
                                           cb.invokestatic(
                                                   CD_RetransformAgent,
                                                   "callTracker", MTD_void_int);
                                        })
                                   .apply();
                    /*** debugging ...
                         if (newcf != null) {
                            String fname = trname + (redef?"_redef" : "") + "/" + className;
                            System.err.println("dumping to: " + fname);
                            write_buffer(fname + "_before.class", classfileBuffer);
                            write_buffer(fname + "_instr.class", newcf);
                         }
                    ***/
                    System.err.println(trname + ": " + className + " index: " + fixedIndex +
                                       (redef? " REDEF" : " LOAD") +
                                       " len before: " + classfileBuffer.length +
                                       " after: " + newcf.length);
                    return newcf;
                } catch (Throwable ex) {
                    System.err.println("Injection failure: " + ex);
                    ex.printStackTrace();
                }
            }
            return null;
        }
    }

    static void write_buffer(String fname, byte[]buffer) {
        try {
            File f = new File(fname);
            if (!f.getParentFile().exists()) {
                f.getParentFile().mkdirs();
            }
            try (FileOutputStream outStream = new FileOutputStream(f)) {
                outStream.write(buffer, 0, buffer.length);
            }
        } catch (IOException ex) {
            System.err.println("EXCEPTION in write_buffer: " + ex);
        }
    }

    public static void premain (String agentArgs, Instrumentation instArg) {
        inst = instArg;
        System.err.println("Premain");

        t1 = new Tr("TR1", false, 10, true, 11, "RetransformApp", "foo");
        inst.addTransformer(t1, true);
        t2 = new Tr("TN2", true,  20, true, 21, "RetransformApp", "foo");
        inst.addTransformer(t2, false);
        t3 = new Tr("TR3", true,  30, true, 31, "RetransformApp", "foo");
        inst.addTransformer(t3, true);
        t4 = new Tr("TN4", true,  40, true, 41, "RetransformApp", "foo");
        inst.addTransformer(t4, false);
    }

    public static void undo() {
        inst.removeTransformer(t3);
        try {
            System.err.println("RETRANSFORM");
            inst.retransformClasses(new RetransformApp().getClass());
        } catch (Exception ex) {
            System.err.println("EXCEPTION on undo: " + ex);
        }
    }

    public static boolean succeeded() {
        return succeeded && markCount == markGolden.length;
    }

    public static void callTracker(int mark) {
        System.err.println("got mark " + mark);
        if (markCount >= markGolden.length || mark != markGolden[markCount++]) {
            succeeded = false;
        }
    }
}
