/*
 * Copyright (c) 2016, 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.
 */
package org.graalvm.compiler.core.common.spi;

import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionValue;

import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaType;

/**
 * Utility for default constant folding semantics for Java fields.
 */
public abstract class JavaConstantFieldProvider implements ConstantFieldProvider {

    static class Options {
        @Option(help = "Determines whether to treat final fields with default values as constant.")//
        public static final OptionValue<Boolean> TrustFinalDefaultFields = new OptionValue<>(true);
    }

    protected JavaConstantFieldProvider(MetaAccessProvider metaAccess) {
        try {
            this.stringValueField = metaAccess.lookupJavaField(String.class.getDeclaredField("value"));
            this.stringHashField = metaAccess.lookupJavaField(String.class.getDeclaredField("hash"));
        } catch (NoSuchFieldException | SecurityException e) {
            throw new GraalError(e);
        }
    }

    @Override
    public <T> T readConstantField(ResolvedJavaField field, ConstantFieldTool<T> tool) {
        if (isStableField(field, tool)) {
            JavaConstant value = tool.readValue();
            if (value != null && isStableFieldValueConstant(field, value, tool)) {
                return foldStableArray(value, field, tool);
            }
        }
        if (isFinalField(field, tool)) {
            JavaConstant value = tool.readValue();
            if (value != null && isFinalFieldValueConstant(field, value, tool)) {
                return tool.foldConstant(value);
            }
        }
        return null;
    }

    protected <T> T foldStableArray(JavaConstant value, ResolvedJavaField field, ConstantFieldTool<T> tool) {
        return tool.foldStableArray(value, getArrayDimension(field.getType()), isDefaultStableField(field, tool));
    }

    private static int getArrayDimension(JavaType type) {
        int dimensions = 0;
        JavaType componentType = type;
        while ((componentType = componentType.getComponentType()) != null) {
            dimensions++;
        }
        return dimensions;
    }

    private static boolean isArray(ResolvedJavaField field) {
        JavaType fieldType = field.getType();
        return fieldType instanceof ResolvedJavaType && ((ResolvedJavaType) fieldType).isArray();
    }

    @SuppressWarnings("unused")
    protected boolean isStableFieldValueConstant(ResolvedJavaField field, JavaConstant value, ConstantFieldTool<?> tool) {
        return !value.isDefaultForKind();
    }

    @SuppressWarnings("unused")
    protected boolean isFinalFieldValueConstant(ResolvedJavaField field, JavaConstant value, ConstantFieldTool<?> tool) {
        return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue();
    }

    @SuppressWarnings("unused")
    protected boolean isStableField(ResolvedJavaField field, ConstantFieldTool<?> tool) {
        if (isSyntheticEnumSwitchMap(field)) {
            return true;
        }
        if (isWellKnownImplicitStableField(field)) {
            return true;
        }
        if (field == stringHashField) {
            return true;
        }
        return false;
    }

    protected boolean isDefaultStableField(ResolvedJavaField field, ConstantFieldTool<?> tool) {
        assert isStableField(field, tool);
        if (isSyntheticEnumSwitchMap(field)) {
            return true;
        }
        return false;
    }

    @SuppressWarnings("unused")
    protected boolean isFinalField(ResolvedJavaField field, ConstantFieldTool<?> tool) {
        return field.isFinal();
    }

    protected boolean isSyntheticEnumSwitchMap(ResolvedJavaField field) {
        if (field.isSynthetic() && field.isStatic() && isArray(field)) {
            String name = field.getName();
            if (field.isFinal() && name.equals("$VALUES") || name.equals("ENUM$VALUES")) {
                // generated int[] field for EnumClass::values()
                return true;
            } else if (name.startsWith("$SwitchMap$") || name.startsWith("$SWITCH_TABLE$")) {
                // javac and ecj generate a static field in an inner class for a switch on an enum
                // named $SwitchMap$p$k$g$EnumClass and $SWITCH_TABLE$p$k$g$EnumClass, respectively
                return true;
            }
        }
        return false;
    }

    private final ResolvedJavaField stringValueField;
    private final ResolvedJavaField stringHashField;

    protected boolean isWellKnownImplicitStableField(ResolvedJavaField field) {
        return field.equals(stringValueField);
    }
}
