/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.openjpa.enhance;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.BytecodeWriter;
import org.apache.openjpa.lib.util.Files;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.Localizer.Message;
import org.apache.openjpa.meta.AccessCode;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.Exceptions;
import org.apache.openjpa.util.GeneratedClasses;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.MetaDataException;
import org.apache.openjpa.util.UserException;

import serp.bytecode.BCClass;

/**
 * Redefines the method bodies of existing unenhanced classes to make them
 * notify state managers of mutations.
 *
 * @since 1.0.0
 */
public class ManagedClassSubclasser {
    private static final Localizer _loc = Localizer.forPackage(
        ManagedClassSubclasser.class);

    /**
     * For each element in <code>classes</code>, creates and registers a
     * new subclass that implements {@link PersistenceCapable}, and prepares
     * OpenJPA to handle new instances of the unenhanced type. If this is
     * invoked in a Java 6 environment, this method will redefine the methods
     * for each class in the argument list such that field accesses are
     * intercepted in-line. If invoked in a Java 5 environment, this
     * redefinition is not possible; in these contexts, when using field
     * access, OpenJPA will need to do state comparisons to detect any change
     * to any instance at any time, and when using property access, OpenJPA
     * will need to do state comparisons to detect changes to newly inserted
     * instances after a flush has been called.
     *
     * @return the new subclasses, or <code>null</code> if <code>classes</code>
     * is <code>null</code>.
     * @throws UserException if <code>conf</code> requires build-time
     * enhancement and <code>classes</code> includes unenhanced types.
     *
     * @since 1.0.0
     */
    public static List<Class<?>> prepareUnenhancedClasses(
        final OpenJPAConfiguration conf,
        final Collection<? extends Class<?>> classes,
        final ClassLoader envLoader) {
        if (classes == null)
            return null;
        if (classes.size() == 0)
            return Collections.emptyList();

        Log log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE);
        if (conf.getRuntimeUnenhancedClassesConstant() != RuntimeUnenhancedClassesModes.SUPPORTED) {
            Collection<Class<?>> unenhanced = new ArrayList<>();
            for (Class<?> cls : classes)
                if (!PersistenceCapable.class.isAssignableFrom(cls))
                    unenhanced.add(cls);
            if (unenhanced.size() > 0) {
                if (PCEnhancerAgent.getLoadSuccessful()) {
                    // This means that the enhancer has been ran but we
                    // have some unenhanced classes. This can happen if an
                    // entity is loaded by the JVM before the EntityManger
                    // was created. Warn the user.
                    if (log.isWarnEnabled()) {
                        log.warn(_loc.get("entities-loaded-before-em"));
                    }
                    if (log.isTraceEnabled()) {
                        log.trace(ManagedClassSubclasser.class.getName()
                            + ".prepareUnenhancedClasses()"
                            + " - The following classes are unenhanced "
                            + unenhanced.toString());
                    }
                }
                Message msg = _loc.get("runtime-optimization-disabled", Exceptions.toClassNames(unenhanced));
                if (conf.getRuntimeUnenhancedClassesConstant() == RuntimeUnenhancedClassesModes.WARN) {
                    log.warn(msg);
                } else {
                    throw new UserException(msg);
                }
            }
            return null;
        }

        boolean redefine = ClassRedefiner.canRedefineClasses(log);
        if (redefine) {
            log.info(_loc.get("enhance-and-subclass-and-redef-start", classes));
        } else {
            log.warn(_loc.get("enhance-and-subclass-no-redef-start",  classes));
        }
        final Map<Class<?>, byte[]> map = new HashMap<>();
        final List<Class<?>> subs = new ArrayList<>(classes.size());
        final List<Class<?>> ints = new ArrayList<>(classes.size());
        Set<Class<?>> unspecified = null;
        for (Class<?> cls : classes) {
            final Class<?> c = cls;
            final PCEnhancer enhancer = new PCEnhancer(conf, cls);

            enhancer.setBytecodeWriter(new BytecodeWriter() {
                @Override
                public void write(BCClass bc) throws IOException {
                    ManagedClassSubclasser.write(bc, enhancer, map, c, subs, ints);
                }
            });
            if (redefine) {
                enhancer.setRedefine(true);
            }

            // we need to create subclasses because class retransform doesn't allow to change the interfaces of a previously loaded class
            enhancer.setCreateSubclass(true);
            enhancer.setAddDefaultConstructor(true);

            // set this before enhancement as well as after since enhancement
            // uses a different metadata repository, and the metadata config
            // matters in the enhancement contract. In order to avoid a
            // NullPointerException, check for no metadata and throw an
            // exception if none exists. Otherwise, don't do any warning here,
            // since we'll issue warnings when we do the final metadata
            // reconfiguration at the end of this method.
            ClassMetaData meta = enhancer.getMetaData();
            if (meta == null) {
                throw new MetaDataException(_loc.get("no-meta", cls)).setFatal(true);
            }
            configureMetaData(meta, conf, redefine, false);

            unspecified = collectRelatedUnspecifiedTypes(enhancer.getMetaData(), classes, unspecified);

            int runResult = enhancer.run();
            if (runResult == PCEnhancer.ENHANCE_PC) {
                try {
                    enhancer.record();
                } catch (IOException e) {
                    // our impl of BytecodeWriter doesn't throw IOException
                    throw new InternalException(e);
                }
            }
        }

        if (unspecified != null && !unspecified.isEmpty())
            throw new UserException(_loc.get("unspecified-unenhanced-types", Exceptions.toClassNames(classes),
                    unspecified));

        ClassRedefiner.redefineClasses(conf, map);
        for (Class<?> cls : map.keySet()) {
            setIntercepting(conf, envLoader, cls);
            configureMetaData(conf, envLoader, cls, redefine);
        }
        for (Class<?> cls : subs)
            configureMetaData(conf, envLoader, cls, redefine);
        for (Class<?> cls : ints)
            setIntercepting(conf, envLoader, cls);

        return subs;
    }

    private static Set<Class<?>> collectRelatedUnspecifiedTypes(ClassMetaData meta,
        Collection<? extends Class<?>> classes, Set<Class<?>> unspecified) {
        unspecified = collectUnspecifiedType(meta.getPCSuperclass(), classes,
            unspecified);

        for (FieldMetaData fmd : meta.getFields()) {
            if (fmd.isTransient())
                continue;
            if (fmd.isTypePC())
                unspecified = collectUnspecifiedType(fmd.getType(), classes,
                    unspecified);
            if (fmd.getElement() != null && fmd.getElement().isTypePC())
                unspecified = collectUnspecifiedType(fmd.getElement().getType(),
                    classes, unspecified);
            if (fmd.getKey() != null && fmd.getKey().isTypePC())
                unspecified = collectUnspecifiedType(fmd.getKey().getType(),
                    classes, unspecified);
            if (fmd.getValue() != null && fmd.getValue().isTypePC())
                unspecified = collectUnspecifiedType(fmd.getValue().getType(),
                    classes, unspecified);
        }
        return unspecified;
    }

    private static Set<Class<?>> collectUnspecifiedType(Class<?> cls,
        Collection<? extends Class<?>> classes, Set<Class<?>> unspecified) {
        if (cls != null && !classes.contains(cls)
            && !ImplHelper.isManagedType(null, cls)
            && !cls.isInterface()) {
            if (unspecified == null)
                unspecified = new HashSet<>();
            unspecified.add(cls);
        }
        return unspecified;
    }

    private static void configureMetaData(OpenJPAConfiguration conf,
        ClassLoader envLoader, Class<?> cls, boolean redefineAvailable) {
        ClassMetaData meta = conf.getMetaDataRepositoryInstance()
            .getMetaData(cls, envLoader, true);
        configureMetaData(meta, conf, redefineAvailable, true);
    }

    private static void configureMetaData(ClassMetaData meta,
        OpenJPAConfiguration conf, boolean redefineAvailable, boolean warn) {

        setDetachedState(meta);

        // If warn & (implicit field access | mixed access) & noredef
        if (warn && ((AccessCode.isField(meta.getAccessType())
            && !meta.isMixedAccess()) ||  meta.isMixedAccess())
            && !redefineAvailable) {
            // only warn about declared fields; superclass fields will be
            // warned about when the superclass is handled
            for (FieldMetaData fmd : meta.getDeclaredFields()) {
                if (AccessCode.isProperty(fmd.getAccessType()))
                    continue;
                switch (fmd.getTypeCode()) {
                    case JavaTypes.COLLECTION:
                    case JavaTypes.MAP:
                        // we can lazily load these, since we own the
                        // relationship container
                        break;
                    default:
                        if (!fmd.isInDefaultFetchGroup()
                            && !(fmd.isVersion() || fmd.isPrimaryKey())) {
                            Log log = conf.getLog(
                                OpenJPAConfiguration.LOG_ENHANCE);
                            log.warn(_loc.get("subclasser-fetch-group-override",
                                meta.getDescribedType().getName(),
                                fmd.getName()));
                            fmd.setInDefaultFetchGroup(true);
                        }
                }
            }
        }
    }

    private static void write(BCClass bc, PCEnhancer enhancer,
        Map<Class<?>, byte[]> map, Class<?> cls, List<Class<?>> subs, List<Class<?>> ints)
        throws IOException {

        if (bc == enhancer.getManagedTypeBytecode()) {
            // if it was already defined, don't put it in the map,
            // but do set the metadata accordingly.
            if (enhancer.isAlreadyRedefined())
                ints.add(bc.getType());
            else {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                AsmAdaptor.write(bc, baos);
                map.put(bc.getType(), baos.toByteArray());
                debugBytecodes(bc);
            }
        } else {
            if (!enhancer.isAlreadySubclassed()) {
                debugBytecodes(bc);

                // this is the new subclass
                ClassLoader loader = GeneratedClasses.getMostDerivedLoader(
                    cls, PersistenceCapable.class);
                subs.add(GeneratedClasses.loadBCClass(bc, loader));
            }
        }
    }

    public static void debugBytecodes(BCClass bc) throws IOException {
        // Write the bytecodes to disk for debugging purposes.
        if ("true".equals(System.getProperty(
            ManagedClassSubclasser.class.getName() + ".dumpBytecodes")))
        {
            File tmp = new File(System.getProperty("java.io.tmpdir"));
            File dir = new File(tmp, "openjpa");
            dir = new File(dir, "pcsubclasses");
            dir.mkdirs();
            dir = Files.getPackageFile(dir, bc.getPackageName(), true);
            File f = new File(dir, bc.getClassName() + ".class");
            // START - ALLOW PRINT STATEMENTS
            System.err.println("Writing to " + f);
            // STOP - ALLOW PRINT STATEMENTS
            AsmAdaptor.write(bc, f);
        }
    }

    private static void setIntercepting(OpenJPAConfiguration conf,
        ClassLoader envLoader, Class<?> cls) {
        ClassMetaData meta = conf.getMetaDataRepositoryInstance()
            .getMetaData(cls, envLoader, true);
        meta.setIntercepting(true);
    }

    /**
     * If the metadata is configured to use a synthetic
     * detached state, reset it to not use a detached
     * state field, since we can't add fields when redefining.
     */
    private static void setDetachedState(ClassMetaData meta) {
        if (ClassMetaData.SYNTHETIC.equals(meta.getDetachedState()))
            meta.setDetachedState(null);
    }
}
