/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.tools.layoutlib.create;

import com.android.tools.layoutlib.java.LinkedHashMap_Delegate;
import com.android.tools.layoutlib.java.System_Delegate;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * Replaces calls to certain methods that do not exist in the Desktop VM. Useful for methods in the
 * "java" package.
 */
public class ReplaceMethodCallsAdapter extends ClassVisitor {

    /**
     * Descriptors for specialized versions {@link System#arraycopy} that are not present on the
     * Desktop VM.
     */
    private static Set<String> ARRAYCOPY_DESCRIPTORS = new HashSet<String>(Arrays.asList(
            "([CI[CII)V", "([BI[BII)V", "([SI[SII)V", "([II[III)V",
            "([JI[JII)V", "([FI[FII)V", "([DI[DII)V", "([ZI[ZII)V"));

    private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<MethodReplacer>(5);

    private static final String ANDROID_LOCALE_CLASS =
            "com/android/layoutlib/bridge/android/AndroidLocale";

    private static final String JAVA_LOCALE_CLASS = Type.getInternalName(java.util.Locale.class);
    private static final Type STRING = Type.getType(String.class);

    private static final String JAVA_LANG_SYSTEM = Type.getInternalName(System.class);

    // Static initialization block to initialize METHOD_REPLACERS.
    static {
        // Case 1: java.lang.System.arraycopy()
        METHOD_REPLACERS.add(new MethodReplacer() {
            @Override
            public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
                return JAVA_LANG_SYSTEM.equals(owner) && "arraycopy".equals(name) &&
                        ARRAYCOPY_DESCRIPTORS.contains(desc);
            }

            @Override
            public void replace(MethodInformation mi) {
                mi.desc = "(Ljava/lang/Object;ILjava/lang/Object;II)V";
            }
        });

        // Case 2: java.util.Locale.toLanguageTag() and java.util.Locale.getScript()
        METHOD_REPLACERS.add(new MethodReplacer() {

            private final String LOCALE_TO_STRING =
                    Type.getMethodDescriptor(STRING, Type.getType(Locale.class));

            @Override
            public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
                return JAVA_LOCALE_CLASS.equals(owner) && "()Ljava/lang/String;".equals(desc) &&
                        ("toLanguageTag".equals(name) || "getScript".equals(name));
            }

            @Override
            public void replace(MethodInformation mi) {
                mi.opcode = Opcodes.INVOKESTATIC;
                mi.owner = ANDROID_LOCALE_CLASS;
                mi.desc = LOCALE_TO_STRING;
            }
        });

        // Case 3: java.util.Locale.adjustLanguageCode() or java.util.Locale.forLanguageTag()
        METHOD_REPLACERS.add(new MethodReplacer() {

            private final String STRING_TO_STRING = Type.getMethodDescriptor(STRING, STRING);
            private final String STRING_TO_LOCALE = Type.getMethodDescriptor(
                    Type.getType(Locale.class), STRING);

            @Override
            public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
                return JAVA_LOCALE_CLASS.equals(owner) &&
                        ("adjustLanguageCode".equals(name) && desc.equals(STRING_TO_STRING) ||
                        "forLanguageTag".equals(name) && desc.equals(STRING_TO_LOCALE));
            }

            @Override
            public void replace(MethodInformation mi) {
                mi.owner = ANDROID_LOCALE_CLASS;
            }
        });

        // Case 4: java.lang.System.log?()
        METHOD_REPLACERS.add(new MethodReplacer() {
            @Override
            public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
                return JAVA_LANG_SYSTEM.equals(owner) && name.length() == 4
                        && name.startsWith("log");
            }

            @Override
            public void replace(MethodInformation mi) {
                assert mi.desc.equals("(Ljava/lang/String;Ljava/lang/Throwable;)V")
                        || mi.desc.equals("(Ljava/lang/String;)V");
                mi.name = "log";
                mi.owner = Type.getInternalName(System_Delegate.class);
            }
        });

        // Case 5: java.util.LinkedHashMap.eldest()
        METHOD_REPLACERS.add(new MethodReplacer() {

            private final String VOID_TO_MAP_ENTRY =
                    Type.getMethodDescriptor(Type.getType(Map.Entry.class));
            private final String LINKED_HASH_MAP = Type.getInternalName(LinkedHashMap.class);

            @Override
            public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
                return LINKED_HASH_MAP.equals(owner) &&
                        "eldest".equals(name) &&
                        VOID_TO_MAP_ENTRY.equals(desc);
            }

            @Override
            public void replace(MethodInformation mi) {
                mi.opcode = Opcodes.INVOKESTATIC;
                mi.owner = Type.getInternalName(LinkedHashMap_Delegate.class);
                mi.desc = Type.getMethodDescriptor(
                        Type.getType(Map.Entry.class), Type.getType(LinkedHashMap.class));
            }
        });

        // Case 6: android.content.Context.getClassLoader() in LayoutInflater
        METHOD_REPLACERS.add(new MethodReplacer() {
            // When LayoutInflater asks for a class loader, we must return the class loader that
            // cannot return app's custom views/classes. This is so that in case of any failure
            // or exception when instantiating the views, the IDE can replace it with a mock view
            // and have proper error handling. However, if a custom view asks for the class
            // loader, we must return a class loader that can find app's custom views as well.
            // Thus, we rewrite the call to get class loader in LayoutInflater to
            // getFrameworkClassLoader and inject a new method in Context. This leaves the normal
            // method: Context.getClassLoader() free to be used by the apps.
            private final String VOID_TO_CLASS_LOADER =
                    Type.getMethodDescriptor(Type.getType(ClassLoader.class));

            @Override
            public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
                return owner.equals("android/content/Context") &&
                        sourceClass.equals("android/view/LayoutInflater") &&
                        name.equals("getClassLoader") &&
                        desc.equals(VOID_TO_CLASS_LOADER);
            }

            @Override
            public void replace(MethodInformation mi) {
                mi.name = "getFrameworkClassLoader";
            }
        });
    }

    /**
     * If a method some.package.Class.Method(args) is called from some.other.Class,
     * @param owner some/package/Class
     * @param name Method
     * @param desc (args)returnType
     * @param sourceClass some/other/Class
     * @return if the method invocation needs to be replaced by some other class.
     */
    public static boolean isReplacementNeeded(String owner, String name, String desc,
            String sourceClass) {
        for (MethodReplacer replacer : METHOD_REPLACERS) {
            if (replacer.isNeeded(owner, name, desc, sourceClass)) {
                return true;
            }
        }
        return false;
    }

    private final String mOriginalClassName;

    public ReplaceMethodCallsAdapter(ClassVisitor cv, String originalClassName) {
        super(Opcodes.ASM4, cv);
        mOriginalClassName = originalClassName;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature,
            String[] exceptions) {
        return new MyMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions));
    }

    private class MyMethodVisitor extends MethodVisitor {

        public MyMethodVisitor(MethodVisitor mv) {
            super(Opcodes.ASM4, mv);
        }

        @Override
        public void visitMethodInsn(int opcode, String owner, String name, String desc) {
            for (MethodReplacer replacer : METHOD_REPLACERS) {
                if (replacer.isNeeded(owner, name, desc, mOriginalClassName)) {
                    MethodInformation mi = new MethodInformation(opcode, owner, name, desc);
                    replacer.replace(mi);
                    opcode = mi.opcode;
                    owner = mi.owner;
                    name = mi.name;
                    desc = mi.desc;
                    break;
                }
            }
            super.visitMethodInsn(opcode, owner, name, desc);
        }
    }

    private static class MethodInformation {
        public int opcode;
        public String owner;
        public String name;
        public String desc;

        public MethodInformation(int opcode, String owner, String name, String desc) {
            this.opcode = opcode;
            this.owner = owner;
            this.name = name;
            this.desc = desc;
        }
    }

    private interface MethodReplacer {
        boolean isNeeded(String owner, String name, String desc, String sourceClass);

        /**
         * Updates the MethodInformation with the new values of the method attributes -
         * opcode, owner, name and desc.
         */
        void replace(MethodInformation mi);
    }
}
