/*
 * Copyright (C) 2007 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.dex.code;

import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.rop.code.SourcePosition;
import com.android.dx.rop.cst.Constant;

/**
 * Instruction which has a single constant argument in addition
 * to all the normal instruction information.
 */
public final class CstInsn extends FixedSizeInsn {
    /** {@code non-null;} the constant argument for this instruction */
    private final Constant constant;

    /**
     * {@code >= -1;} the constant pool index for {@link #constant}, or
     * {@code -1} if not yet set
     */
    private int index;

    /**
     * {@code >= -1;} the constant pool index for the class reference in
     * {@link #constant} if any, or {@code -1} if not yet set
     */
    private int classIndex;

    /**
     * Constructs an instance. The output address of this instance is
     * initially unknown ({@code -1}) as is the constant pool index.
     *
     * @param opcode the opcode; one of the constants from {@link Dops}
     * @param position {@code non-null;} source position
     * @param registers {@code non-null;} register list, including a
     * result register if appropriate (that is, registers may be either
     * ins or outs)
     * @param constant {@code non-null;} constant argument
     */
    public CstInsn(Dop opcode, SourcePosition position,
                   RegisterSpecList registers, Constant constant) {
        super(opcode, position, registers);

        if (constant == null) {
            throw new NullPointerException("constant == null");
        }

        this.constant = constant;
        this.index = -1;
        this.classIndex = -1;
    }

    /** {@inheritDoc} */
    @Override
    public DalvInsn withOpcode(Dop opcode) {
        CstInsn result =
            new CstInsn(opcode, getPosition(), getRegisters(), constant);

        if (index >= 0) {
            result.setIndex(index);
        }

        if (classIndex >= 0) {
            result.setClassIndex(classIndex);
        }

        return result;
    }

    /** {@inheritDoc} */
    @Override
    public DalvInsn withRegisters(RegisterSpecList registers) {
        CstInsn result =
            new CstInsn(getOpcode(), getPosition(), registers, constant);

        if (index >= 0) {
            result.setIndex(index);
        }

        if (classIndex >= 0) {
            result.setClassIndex(classIndex);
        }

        return result;
    }

    /**
     * Gets the constant argument.
     *
     * @return {@code non-null;} the constant argument
     */
    public Constant getConstant() {
        return constant;
    }

    /**
     * Gets the constant's index. It is only valid to call this after
     * {@link #setIndex} has been called.
     *
     * @return {@code >= 0;} the constant pool index
     */
    public int getIndex() {
        if (index < 0) {
            throw new RuntimeException("index not yet set for " + constant);
        }

        return index;
    }

    /**
     * Returns whether the constant's index has been set for this instance.
     *
     * @see #setIndex
     *
     * @return {@code true} iff the index has been set
     */
    public boolean hasIndex() {
        return (index >= 0);
    }

    /**
     * Sets the constant's index. It is only valid to call this method once
     * per instance.
     *
     * @param index {@code >= 0;} the constant pool index
     */
    public void setIndex(int index) {
        if (index < 0) {
            throw new IllegalArgumentException("index < 0");
        }

        if (this.index >= 0) {
            throw new RuntimeException("index already set");
        }

        this.index = index;
    }

    /**
     * Gets the constant's class index. It is only valid to call this after
     * {@link #setClassIndex} has been called.
     *
     * @return {@code >= 0;} the constant's class's constant pool index
     */
    public int getClassIndex() {
        if (classIndex < 0) {
            throw new RuntimeException("class index not yet set");
        }

        return classIndex;
    }

    /**
     * Returns whether the constant's class index has been set for this
     * instance.
     *
     * @see #setClassIndex
     *
     * @return {@code true} iff the index has been set
     */
    public boolean hasClassIndex() {
        return (classIndex >= 0);
    }

    /**
     * Sets the constant's class index. This is the constant pool index
     * for the class referred to by this instance's constant. Only
     * reference constants have a class, so it is only on instances
     * with reference constants that this method should ever be
     * called. It is only valid to call this method once per instance.
     *
     * @param index {@code >= 0;} the constant's class's constant pool index
     */
    public void setClassIndex(int index) {
        if (index < 0) {
            throw new IllegalArgumentException("index < 0");
        }

        if (this.classIndex >= 0) {
            throw new RuntimeException("class index already set");
        }

        this.classIndex = index;
    }

    /** {@inheritDoc} */
    @Override
    protected String argString() {
        return constant.toHuman();
    }
}
