/*
 * Copyright (C) 2017 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.dx.rop.cst;

import com.android.dx.rop.type.Type;

/**
 * Constants of type {@code MethodHandle}.
 */
public final class CstMethodHandle extends TypedConstant {

    public static final int METHOD_HANDLE_TYPE_STATIC_PUT = 0;
    public static final int METHOD_HANDLE_TYPE_STATIC_GET = 1;
    public static final int METHOD_HANDLE_TYPE_INSTANCE_PUT = 2;
    public static final int METHOD_HANDLE_TYPE_INSTANCE_GET = 3;

    public static final int METHOD_HANDLE_TYPE_INVOKE_STATIC = 4;
    public static final int METHOD_HANDLE_TYPE_INVOKE_INSTANCE = 5;
    public static final int METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR = 6;
    public static final int METHOD_HANDLE_TYPE_INVOKE_DIRECT = 7;
    public static final int METHOD_HANDLE_TYPE_INVOKE_INTERFACE = 8;

    private static final String [] TYPE_NAMES = {
        "static-put", "static-get", "instance-put", "instance-get",
        "invoke-static", "invoke-instance", "invoke-constructor", "invoke-direct",
        "invoke-interface"
    };

    /** The type of MethodHandle */
    private final int type;

    /** {@code non-null;} the referenced constant */
    private final Constant ref;

    /**
     * Makes an instance for the given value. This may (but does not
     * necessarily) return an already-allocated instance.
     *
     * @param type the type of this handle
     * @param ref {@code non-null;} the referenced field or method constant
     * @return {@code non-null;} the appropriate instance
     */
    public static CstMethodHandle make(int type, Constant ref) {
        if (isAccessor(type)) {
            if (!(ref instanceof CstFieldRef)) {
                throw new IllegalArgumentException("ref has wrong type: " + ref.getClass());
            }
        } else if (isInvocation(type)) {
            if (!(ref instanceof CstBaseMethodRef)) {
                throw new IllegalArgumentException("ref has wrong type: " + ref.getClass());
            }
        } else {
            throw new IllegalArgumentException("type is out of range: " + type);
        }
        return new CstMethodHandle(type, ref);
    }

    /**
     * Constructs an instance. This constructor is private; use {@link #make}.
     *
     * @param type the type of this handle
     * @param ref the actual referenced constant
     */
    private CstMethodHandle(int type, Constant ref) {
        this.type = type;
        this.ref = ref;
    }

    /**
     * Gets the actual constant.
     *
     * @return the value
     */
    public Constant getRef() {
        return ref;
    }

    /**
     * Gets the type of this method handle.
     *
     * @return the type
     */
    public int getMethodHandleType() {
        return type;
    }

    /**
     * Reports whether the method handle type is a field accessor.
     *
     * @param type the method handle type
     * @return true if the method handle type is a field accessor, false otherwise
     */
    public static boolean isAccessor(int type) {
        switch (type) {
            case METHOD_HANDLE_TYPE_STATIC_PUT:
            case METHOD_HANDLE_TYPE_STATIC_GET:
            case METHOD_HANDLE_TYPE_INSTANCE_PUT:
            case METHOD_HANDLE_TYPE_INSTANCE_GET:
                return true;
            default:
                return false;
        }
    }

    /**
     * Reports whether the method handle is a field accessor.
     *
     * @return true if the method handle is a field accessor, false otherwise
     */
    public boolean isAccessor() {
        return isAccessor(type);
    }

    /**
     * Reports whether the method handle type is a method invocation.
     *
     * @param type the method handle type
     * @return true if the method handle type is a method invocation, false otherwise
     */
    public static boolean isInvocation(int type) {
        switch (type) {
            case METHOD_HANDLE_TYPE_INVOKE_STATIC:
            case METHOD_HANDLE_TYPE_INVOKE_INSTANCE:
            case METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR:
            case METHOD_HANDLE_TYPE_INVOKE_DIRECT:
            case METHOD_HANDLE_TYPE_INVOKE_INTERFACE:
                return true;
            default:
                return false;
        }
    }

    /**
     * Reports whether the method handle is a method invocation.
     *
     * @return true if the method handle is a method invocation, false otherwise
     */
    public boolean isInvocation() {
        return isInvocation(type);
    }

    /**
     * Gets a human readable name for a method handle type.
     *
     * @param type the method handle type
     * @return the string representation of the type
     */
    private static String getTypeName(final int type) {
        return TYPE_NAMES[type];
    }

    /** {@inheritDoc} */
    @Override
    public boolean isCategory2() {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    protected int compareTo0(Constant other) {
        CstMethodHandle otherHandle = (CstMethodHandle) other;
        if (getMethodHandleType() == otherHandle.getMethodHandleType()) {
            return getRef().compareTo(otherHandle.getRef());
        } else {
            return Integer.compare(getMethodHandleType(), otherHandle.getMethodHandleType());
        }
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return "method-handle{" + toHuman() + "}";
    }

    /** {@inheritDoc} */
    @Override
    public String typeName() {
        return "method handle";
    }

    /** {@inheritDoc} */
    @Override
    public String toHuman() {
        return getTypeName(type)+ "," + ref.toString();
    }

    @Override
    public Type getType() {
        return Type.METHOD_HANDLE;
    }
}
