/*
 * 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.io.Opcodes;
import com.android.dx.rop.code.RegisterSpecList;
import com.android.dx.rop.code.SourcePosition;
import com.android.dx.util.AnnotatedOutput;
import com.android.dx.util.Hex;
import com.android.dx.util.IntList;

/**
 * Pseudo-instruction which holds switch data. The switch data is
 * a map of values to target addresses, and this class writes the data
 * in either a "packed" or "sparse" form.
 */
public final class SwitchData extends VariableSizeInsn {
    /**
     * {@code non-null;} address representing the instruction that uses this
     * instance
     */
    private final CodeAddress user;

    /** {@code non-null;} sorted list of switch cases (keys) */
    private final IntList cases;

    /**
     * {@code non-null;} corresponding list of code addresses; the branch
     * target for each case
     */
    private final CodeAddress[] targets;

    /** whether the output table will be packed (vs. sparse) */
    private final boolean packed;

    /**
     * Constructs an instance. The output address of this instance is initially
     * unknown ({@code -1}).
     *
     * @param position {@code non-null;} source position
     * @param user {@code non-null;} address representing the instruction that
     * uses this instance
     * @param cases {@code non-null;} sorted list of switch cases (keys)
     * @param targets {@code non-null;} corresponding list of code addresses; the
     * branch target for each case
     */
    public SwitchData(SourcePosition position, CodeAddress user,
                      IntList cases, CodeAddress[] targets) {
        super(position, RegisterSpecList.EMPTY);

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

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

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

        int sz = cases.size();

        if (sz != targets.length) {
            throw new IllegalArgumentException("cases / targets mismatch");
        }

        if (sz > 65535) {
            throw new IllegalArgumentException("too many cases");
        }

        this.user = user;
        this.cases = cases;
        this.targets = targets;
        this.packed = shouldPack(cases);
    }

    /** {@inheritDoc} */
    @Override
    public int codeSize() {
        return packed ? (int) packedCodeSize(cases) :
            (int) sparseCodeSize(cases);
    }

    /** {@inheritDoc} */
    @Override
    public void writeTo(AnnotatedOutput out) {
        int baseAddress = user.getAddress();
        int defaultTarget = Dops.PACKED_SWITCH.getFormat().codeSize();
        int sz = targets.length;

        if (packed) {
            int firstCase = (sz == 0) ? 0 : cases.get(0);
            int lastCase = (sz == 0) ? 0 : cases.get(sz - 1);
            int outSz = lastCase - firstCase + 1;

            out.writeShort(Opcodes.PACKED_SWITCH_PAYLOAD);
            out.writeShort(outSz);
            out.writeInt(firstCase);

            int caseAt = 0;
            for (int i = 0; i < outSz; i++) {
                int outCase = firstCase + i;
                int oneCase = cases.get(caseAt);
                int relTarget;

                if (oneCase > outCase) {
                    relTarget = defaultTarget;
                } else {
                    relTarget = targets[caseAt].getAddress() - baseAddress;
                    caseAt++;
                }

                out.writeInt(relTarget);
            }
        } else {
            out.writeShort(Opcodes.SPARSE_SWITCH_PAYLOAD);
            out.writeShort(sz);

            for (int i = 0; i < sz; i++) {
                out.writeInt(cases.get(i));
            }

            for (int i = 0; i < sz; i++) {
                int relTarget = targets[i].getAddress() - baseAddress;
                out.writeInt(relTarget);
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public DalvInsn withRegisters(RegisterSpecList registers) {
        return new SwitchData(getPosition(), user, cases, targets);
    }

    /**
     * Returns whether or not this instance's data will be output as packed.
     *
     * @return {@code true} iff the data is to be packed
     */
    public boolean isPacked() {
        return packed;
    }

    /** {@inheritDoc} */
    @Override
    protected String argString() {
        StringBuffer sb = new StringBuffer(100);

        int sz = targets.length;
        for (int i = 0; i < sz; i++) {
            sb.append("\n    ");
            sb.append(cases.get(i));
            sb.append(": ");
            sb.append(targets[i]);
        }

        return sb.toString();
    }

    /** {@inheritDoc} */
    @Override
    protected String listingString0(boolean noteIndices) {
        int baseAddress = user.getAddress();
        StringBuffer sb = new StringBuffer(100);
        int sz = targets.length;

        sb.append(packed ? "packed" : "sparse");
        sb.append("-switch-payload // for switch @ ");
        sb.append(Hex.u2(baseAddress));

        for (int i = 0; i < sz; i++) {
            int absTarget = targets[i].getAddress();
            int relTarget = absTarget - baseAddress;
            sb.append("\n  ");
            sb.append(cases.get(i));
            sb.append(": ");
            sb.append(Hex.u4(absTarget));
            sb.append(" // ");
            sb.append(Hex.s4(relTarget));
        }

        return sb.toString();
    }

    /**
     * Gets the size of a packed table for the given cases, in 16-bit code
     * units.
     *
     * @param cases {@code non-null;} sorted list of cases
     * @return {@code >= -1;} the packed table size or {@code -1} if the
     * cases couldn't possibly be represented as a packed table
     */
    private static long packedCodeSize(IntList cases) {
        int sz = cases.size();
        long low = cases.get(0);
        long high = cases.get(sz - 1);
        long result = ((high - low + 1)) * 2 + 4;

        return (result <= 0x7fffffff) ? result : -1;
    }

    /**
     * Gets the size of a sparse table for the given cases, in 16-bit code
     * units.
     *
     * @param cases {@code non-null;} sorted list of cases
     * @return {@code > 0;} the sparse table size
     */
    private static long sparseCodeSize(IntList cases) {
        int sz = cases.size();

        return (sz * 4L) + 2;
    }

    /**
     * Determines whether the given list of cases warrant being packed.
     *
     * @param cases {@code non-null;} sorted list of cases
     * @return {@code true} iff the table encoding the cases
     * should be packed
     */
    private static boolean shouldPack(IntList cases) {
        int sz = cases.size();

        if (sz < 2) {
            return true;
        }

        long packedSize = packedCodeSize(cases);
        long sparseSize = sparseCodeSize(cases);

        /*
         * We pick the packed representation if it is possible and
         * would be as small or smaller than 5/4 of the sparse
         * representation. That is, we accept some size overhead on
         * the packed representation, since that format is faster to
         * execute at runtime.
         */
        return (packedSize >= 0) && (packedSize <= ((sparseSize * 5) / 4));
    }
}
