/*
 * 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.RegisterSpec;
import com.android.dx.rop.code.RegisterSpecSet;
import com.android.dx.rop.cst.CstType;
import com.android.dx.rop.cst.CstUtf8;
import com.android.dx.rop.type.Type;
import com.android.dx.util.FixedSizeList;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * List of local variables. Each local variable entry indicates a
 * range of code which it is valid for, a register number, a name,
 * and a type.
 */
public final class LocalList extends FixedSizeList {
    /** {@code non-null;} empty instance */
    public static final LocalList EMPTY = new LocalList(0);

    /** whether to run the self-check code */
    private static final boolean DEBUG = false;

    /**
     * Constructs an instance. All indices initially contain {@code null}.
     *
     * @param size {@code >= 0;} the size of the list
     */
    public LocalList(int size) {
        super(size);
    }

    /**
     * Gets the element at the given index. It is an error to call
     * this with the index for an element which was never set; if you
     * do that, this will throw {@code NullPointerException}.
     *
     * @param n {@code >= 0, < size();} which index
     * @return {@code non-null;} element at that index
     */
    public Entry get(int n) {
        return (Entry) get0(n);
    }

    /**
     * Sets the entry at the given index.
     *
     * @param n {@code >= 0, < size();} which index
     * @param entry {@code non-null;} the entry to set at {@code n}
     */
    public void set(int n, Entry entry) {
        set0(n, entry);
    }

    /**
     * Does a human-friendly dump of this instance.
     *
     * @param out {@code non-null;} where to dump
     * @param prefix {@code non-null;} prefix to attach to each line of output
     */
    public void debugPrint(PrintStream out, String prefix) {
        int sz = size();

        for (int i = 0; i < sz; i++) {
            out.print(prefix);
            out.println(get(i));
        }
    }

    /**
     * Disposition of a local entry.
     */
    public static enum Disposition {
        /** local started (introduced) */
        START,

        /** local ended without being replaced */
        END_SIMPLY,

        /** local ended because it was directly replaced */
        END_REPLACED,

        /** local ended because it was moved to a different register */
        END_MOVED,

        /**
         * local ended because the previous local clobbered this one
         * (because it is category-2)
         */
        END_CLOBBERED_BY_PREV,

        /**
         * local ended because the next local clobbered this one
         * (because this one is a category-2)
         */
        END_CLOBBERED_BY_NEXT;
    }

    /**
     * Entry in a local list.
     */
    public static class Entry implements Comparable<Entry> {
        /** {@code >= 0;} address */
        private final int address;

        /** {@code non-null;} disposition of the local */
        private final Disposition disposition;

        /** {@code non-null;} register spec representing the variable */
        private final RegisterSpec spec;

        /** {@code non-null;} variable type (derived from {@code spec}) */
        private final CstType type;

        /**
         * Constructs an instance.
         *
         * @param address {@code >= 0;} address
         * @param disposition {@code non-null;} disposition of the local
         * @param spec {@code non-null;} register spec representing
         * the variable
         */
        public Entry(int address, Disposition disposition, RegisterSpec spec) {
            if (address < 0) {
                throw new IllegalArgumentException("address < 0");
            }

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

            try {
                if (spec.getLocalItem() == null) {
                    throw new NullPointerException(
                            "spec.getLocalItem() == null");
                }
            } catch (NullPointerException ex) {
                // Elucidate the exception.
                throw new NullPointerException("spec == null");
            }

            this.address = address;
            this.disposition = disposition;
            this.spec = spec;
            this.type = CstType.intern(spec.getType());
        }

        /** {@inheritDoc} */
        public String toString() {
            return Integer.toHexString(address) + " " + disposition + " " +
                spec;
        }

        /** {@inheritDoc} */
        public boolean equals(Object other) {
            if (!(other instanceof Entry)) {
                return false;
            }

            return (compareTo((Entry) other) == 0);
        }

        /**
         * Compares by (in priority order) address, end then start
         * disposition (variants of end are all consistered
         * equivalent), and spec.
         *
         * @param other {@code non-null;} entry to compare to
         * @return {@code -1..1;} standard result of comparison
         */
        public int compareTo(Entry other) {
            if (address < other.address) {
                return -1;
            } else if (address > other.address) {
                return 1;
            }

            boolean thisIsStart = isStart();
            boolean otherIsStart = other.isStart();

            if (thisIsStart != otherIsStart) {
                return thisIsStart ? 1 : -1;
            }

            return spec.compareTo(other.spec);
        }

        /**
         * Gets the address.
         *
         * @return {@code >= 0;} the address
         */
        public int getAddress() {
            return address;
        }

        /**
         * Gets the disposition.
         *
         * @return {@code non-null;} the disposition
         */
        public Disposition getDisposition() {
            return disposition;
        }

        /**
         * Gets whether this is a local start. This is just shorthand for
         * {@code getDisposition() == Disposition.START}.
         *
         * @return {@code true} iff this is a start
         */
        public boolean isStart() {
            return disposition == Disposition.START;
        }

        /**
         * Gets the variable name.
         *
         * @return {@code null-ok;} the variable name
         */
        public CstUtf8 getName() {
            return spec.getLocalItem().getName();
        }

        /**
         * Gets the variable signature.
         *
         * @return {@code null-ok;} the variable signature
         */
        public CstUtf8 getSignature() {
            return spec.getLocalItem().getSignature();
        }

        /**
         * Gets the variable's type.
         *
         * @return {@code non-null;} the type
         */
        public CstType getType() {
            return type;
        }

        /**
         * Gets the number of the register holding the variable.
         *
         * @return {@code >= 0;} the number of the register holding
         * the variable
         */
        public int getRegister() {
            return spec.getReg();
        }

        /**
         * Gets the RegisterSpec of the register holding the variable.
         *
         * @return {@code non-null;} RegisterSpec of the holding register.
         */
        public RegisterSpec getRegisterSpec() {
            return spec;
        }

        /**
         * Returns whether or not this instance matches the given spec.
         *
         * @param spec {@code non-null;} the spec in question
         * @return {@code true} iff this instance matches
         * {@code spec}
         */
        public boolean matches(RegisterSpec otherSpec) {
            return spec.equalsUsingSimpleType(otherSpec);
        }

        /**
         * Returns whether or not this instance matches the spec in
         * the given instance.
         *
         * @param other {@code non-null;} another entry
         * @return {@code true} iff this instance's spec matches
         * {@code other}
         */
        public boolean matches(Entry other) {
            return matches(other.spec);
        }

        /**
         * Returns an instance just like this one but with the disposition
         * set as given.
         *
         * @param disposition {@code non-null;} the new disposition
         * @return {@code non-null;} an appropriately-constructed instance
         */
        public Entry withDisposition(Disposition disposition) {
            if (disposition == this.disposition) {
                return this;
            }

            return new Entry(address, disposition, spec);
        }
    }

    /**
     * Constructs an instance for the given method, based on the given
     * block order and intermediate local information.
     *
     * @param insns {@code non-null;} instructions to convert
     * @return {@code non-null;} the constructed list
     */
    public static LocalList make(DalvInsnList insns) {
        int sz = insns.size();

        /*
         * Go through the insn list, looking for all the local
         * variable pseudoinstructions, splitting out LocalSnapshots
         * into separate per-variable starts, adding explicit ends
         * wherever a variable is replaced or moved, and collecting
         * these and all the other local variable "activity"
         * together into an output list (without the other insns).
         *
         * Note: As of this writing, this method won't be handed any
         * insn lists that contain local ends, but I (danfuzz) expect
         * that to change at some point, when we start feeding that
         * info explicitly into the rop layer rather than only trying
         * to infer it. So, given that expectation, this code is
         * written to deal with them.
         */

        MakeState state = new MakeState(sz);

        for (int i = 0; i < sz; i++) {
            DalvInsn insn = insns.get(i);

            if (insn instanceof LocalSnapshot) {
                RegisterSpecSet snapshot =
                    ((LocalSnapshot) insn).getLocals();
                state.snapshot(insn.getAddress(), snapshot);
            } else if (insn instanceof LocalStart) {
                RegisterSpec local = ((LocalStart) insn).getLocal();
                state.startLocal(insn.getAddress(), local);
            } else if (insn instanceof LocalEnd) {
                RegisterSpec local = ((LocalEnd) insn).getLocal();
                state.endLocal(insn.getAddress(), local);
            }
        }

        LocalList result = state.finish();

        if (DEBUG) {
            debugVerify(result);
        }

        return result;
    }

    /**
     * Debugging helper that verifies the constraint that a list doesn't
     * contain any redundant local starts and that local ends that are
     * due to replacements are properly annotated.
     */
    private static void debugVerify(LocalList locals) {
        try {
            debugVerify0(locals);
        } catch (RuntimeException ex) {
            int sz = locals.size();
            for (int i = 0; i < sz; i++) {
                System.err.println(locals.get(i));
            }
            throw ex;
        }

    }

    /**
     * Helper for {@link #debugVerify} which does most of the work.
     */
    private static void debugVerify0(LocalList locals) {
        int sz = locals.size();
        Entry[] active = new Entry[65536];

        for (int i = 0; i < sz; i++) {
            Entry e = locals.get(i);
            int reg = e.getRegister();

            if (e.isStart()) {
                Entry already = active[reg];

                if ((already != null) && e.matches(already)) {
                    throw new RuntimeException("redundant start at " +
                            Integer.toHexString(e.getAddress()) + ": got " +
                            e + "; had " + already);
                }

                active[reg] = e;
            } else {
                if (active[reg] == null) {
                    throw new RuntimeException("redundant end at " +
                            Integer.toHexString(e.getAddress()));
                }

                int addr = e.getAddress();
                boolean foundStart = false;

                for (int j = i + 1; j < sz; j++) {
                    Entry test = locals.get(j);
                    if (test.getAddress() != addr) {
                        break;
                    }
                    if (test.getRegisterSpec().getReg() == reg) {
                        if (test.isStart()) {
                            if (e.getDisposition()
                                    != Disposition.END_REPLACED) {
                                throw new RuntimeException(
                                        "improperly marked end at " +
                                        Integer.toHexString(addr));
                            }
                            foundStart = true;
                        } else {
                            throw new RuntimeException(
                                    "redundant end at " +
                                    Integer.toHexString(addr));
                        }
                    }
                }

                if (!foundStart &&
                        (e.getDisposition() == Disposition.END_REPLACED)) {
                    throw new RuntimeException(
                            "improper end replacement claim at " +
                            Integer.toHexString(addr));
                }

                active[reg] = null;
            }
        }
    }

    /**
     * Intermediate state when constructing a local list.
     */
    public static class MakeState {
        /** {@code non-null;} result being collected */
        private final ArrayList<Entry> result;

        /**
         * {@code >= 0;} running count of nulled result entries, to help with
         * sizing the final list
         */
        private int nullResultCount;

        /** {@code null-ok;} current register mappings */
        private RegisterSpecSet regs;

        /** {@code null-ok;} result indices where local ends are stored */
        private int[] endIndices;

        /** {@code >= 0;} last address seen */
        private int lastAddress;

        /**
         * Constructs an instance.
         */
        public MakeState(int initialSize) {
            result = new ArrayList<Entry>(initialSize);
            nullResultCount = 0;
            regs = null;
            endIndices = null;
            lastAddress = 0;
        }

        /**
         * Checks the address and other vitals as a prerequisite to
         * further processing.
         *
         * @param address {@code >= 0;} address about to be processed
         * @param reg {@code >= 0;} register number about to be processed
         */
        private void aboutToProcess(int address, int reg) {
            boolean first = (endIndices == null);

            if ((address == lastAddress) && !first) {
                return;
            }

            if (address < lastAddress) {
                throw new RuntimeException("shouldn't happen");
            }

            if (first || (reg >= endIndices.length)) {
                /*
                 * This is the first allocation of the state set and
                 * index array, or we need to grow. (The latter doesn't
                 * happen much; in fact, we have only ever observed
                 * it happening in test cases, never in "real" code.)
                 */
                int newSz = reg + 1;
                RegisterSpecSet newRegs = new RegisterSpecSet(newSz);
                int[] newEnds = new int[newSz];
                Arrays.fill(newEnds, -1);

                if (!first) {
                    newRegs.putAll(regs);
                    System.arraycopy(endIndices, 0, newEnds, 0,
                            endIndices.length);
                }

                regs = newRegs;
                endIndices = newEnds;
            }
        }

        /**
         * Sets the local state at the given address to the given snapshot.
         * The first call on this instance must be to this method, so that
         * the register state can be properly sized.
         *
         * @param address {@code >= 0;} the address
         * @param specs {@code non-null;} spec set representing the locals
         */
        public void snapshot(int address, RegisterSpecSet specs) {
            if (DEBUG) {
                System.err.printf("%04x snapshot %s\n", address, specs);
            }

            int sz = specs.getMaxSize();
            aboutToProcess(address, sz - 1);

            for (int i = 0; i < sz; i++) {
                RegisterSpec oldSpec = regs.get(i);
                RegisterSpec newSpec = filterSpec(specs.get(i));

                if (oldSpec == null) {
                    if (newSpec != null) {
                        startLocal(address, newSpec);
                    }
                } else if (newSpec == null) {
                    endLocal(address, oldSpec);
                } else if (! newSpec.equalsUsingSimpleType(oldSpec)) {
                    endLocal(address, oldSpec);
                    startLocal(address, newSpec);
                }
            }

            if (DEBUG) {
                System.err.printf("%04x snapshot done\n", address);
            }
        }

        /**
         * Starts a local at the given address.
         *
         * @param address {@code >= 0;} the address
         * @param startedLocal {@code non-null;} spec representing the
         * started local
         */
        public void startLocal(int address, RegisterSpec startedLocal) {
            if (DEBUG) {
                System.err.printf("%04x start %s\n", address, startedLocal);
            }

            int regNum = startedLocal.getReg();

            startedLocal = filterSpec(startedLocal);
            aboutToProcess(address, regNum);

            RegisterSpec existingLocal = regs.get(regNum);

            if (startedLocal.equalsUsingSimpleType(existingLocal)) {
                // Silently ignore a redundant start.
                return;
            }

            RegisterSpec movedLocal = regs.findMatchingLocal(startedLocal);
            if (movedLocal != null) {
                /*
                 * The same variable was moved from one register to another.
                 * So add an end for its old location.
                 */
                addOrUpdateEnd(address, Disposition.END_MOVED, movedLocal);
            }

            int endAt = endIndices[regNum];

            if (existingLocal != null) {
                /*
                 * There is an existing (but non-matching) local.
                 * Add an explicit end for it.
                 */
                add(address, Disposition.END_REPLACED, existingLocal);
            } else if (endAt >= 0) {
                /*
                 * Look for an end local for the same register at the
                 * same address. If found, then update it or delete
                 * it, depending on whether or not it represents the
                 * same variable as the one being started.
                 */
                Entry endEntry = result.get(endAt);
                if (endEntry.getAddress() == address) {
                    if (endEntry.matches(startedLocal)) {
                        /*
                         * There was already an end local for the same
                         * variable at the same address. This turns
                         * out to be superfluous, as we are starting
                         * up the exact same local. This situation can
                         * happen when a single local variable got
                         * somehow "split up" during intermediate
                         * processing. In any case, rather than represent
                         * the end-then-start, just remove the old end.
                         */
                        result.set(endAt, null);
                        nullResultCount++;
                        regs.put(startedLocal);
                        endIndices[regNum] = -1;
                        return;
                    } else {
                        /*
                         * There was a different variable ended at the
                         * same address. Update it to indicate that
                         * it was ended due to a replacement (rather than
                         * ending for no particular reason).
                         */
                        endEntry = endEntry.withDisposition(
                                Disposition.END_REPLACED);
                        result.set(endAt, endEntry);
                    }
                }
            }

            /*
             * The code above didn't find and remove an unnecessary
             * local end, so we now have to add one or more entries to
             * the output to capture the transition.
             */

            /*
             * If the local just below (in the register set at reg-1)
             * is of category-2, then it is ended by this new start.
             */
            if (regNum > 0) {
                RegisterSpec justBelow = regs.get(regNum - 1);
                if ((justBelow != null) && justBelow.isCategory2()) {
                    addOrUpdateEnd(address,
                            Disposition.END_CLOBBERED_BY_NEXT,
                            justBelow);
                }
            }

            /*
             * Similarly, if this local is category-2, then the local
             * just above (if any) is ended by the start now being
             * emitted.
             */
            if (startedLocal.isCategory2()) {
                RegisterSpec justAbove = regs.get(regNum + 1);
                if (justAbove != null) {
                    addOrUpdateEnd(address,
                            Disposition.END_CLOBBERED_BY_PREV,
                            justAbove);
                }
            }

            /*
             * TODO: Add an end for the same local in a different reg,
             * if any (that is, if the local migrates from vX to vY,
             * we should note that as a local end in vX).
             */

            add(address, Disposition.START, startedLocal);
        }

        /**
         * Ends a local at the given address, using the disposition
         * {@code END_SIMPLY}.
         *
         * @param address {@code >= 0;} the address
         * @param endedLocal {@code non-null;} spec representing the
         * local being ended
         */
        public void endLocal(int address, RegisterSpec endedLocal) {
            endLocal(address, endedLocal, Disposition.END_SIMPLY);
        }

        /**
         * Ends a local at the given address.
         *
         * @param address {@code >= 0;} the address
         * @param endedLocal {@code non-null;} spec representing the
         * local being ended
         * @param disposition reason for the end
         */
        public void endLocal(int address, RegisterSpec endedLocal,
                Disposition disposition) {
            if (DEBUG) {
                System.err.printf("%04x end %s\n", address, endedLocal);
            }

            int regNum = endedLocal.getReg();

            endedLocal = filterSpec(endedLocal);
            aboutToProcess(address, regNum);

            int endAt = endIndices[regNum];

            if (endAt >= 0) {
                /*
                 * The local in the given register is already ended.
                 * Silently return without adding anything to the result.
                 */
                return;
            }

            // Check for start and end at the same address.
            if (checkForEmptyRange(address, endedLocal)) {
                return;
            }

            add(address, disposition, endedLocal);
        }

        /**
         * Helper for {@link #endLocal}, which handles the cases where
         * and end local is issued at the same address as a start local
         * for the same register. If this case is found, then this
         * method will remove the start (as the local was never actually
         * active), update the {@link #endIndices} to be accurate, and
         * if needed update the newly-active end to reflect an altered
         * disposition.
         *
         * @param address {@code >= 0;} the address
         * @param endedLocal {@code non-null;} spec representing the
         * local being ended
         * @return {@code true} iff this method found the case in question
         * and adjusted things accordingly
         */
        private boolean checkForEmptyRange(int address,
                RegisterSpec endedLocal) {
            int at = result.size() - 1;
            Entry entry;

            // Look for a previous entry at the same address.
            for (/*at*/; at >= 0; at--) {
                entry = result.get(at);

                if (entry == null) {
                    continue;
                }

                if (entry.getAddress() != address) {
                    // We didn't find any match at the same address.
                    return false;
                }

                if (entry.matches(endedLocal)) {
                    break;
                }
            }

            /*
             * In fact, we found that the endedLocal had started at the
             * same address, so do all the requisite cleanup.
             */

            regs.remove(endedLocal);
            result.set(at, null);
            nullResultCount++;

            int regNum = endedLocal.getReg();
            boolean found = false;
            entry = null;

            // Now look back further to update where the register ended.
            for (at--; at >= 0; at--) {
                entry = result.get(at);

                if (entry == null) {
                    continue;
                }

                if (entry.getRegisterSpec().getReg() == regNum) {
                    found = true;
                    break;
                }
            }

            if (found) {
                // We found an end for the same register.
                endIndices[regNum] = at;

                if (entry.getAddress() == address) {
                    /*
                     * It's still the same address, so update the
                     * disposition.
                     */
                    result.set(at,
                            entry.withDisposition(Disposition.END_SIMPLY));
                }
            }

            return true;
        }

        /**
         * Converts a given spec into the form acceptable for use in a
         * local list. This, in particular, transforms the "known
         * null" type into simply {@code Object}. This method needs to
         * be called for any spec that is on its way into a locals
         * list.
         *
         * <p>This isn't necessarily the cleanest way to achieve the
         * goal of not representing known nulls in a locals list, but
         * it gets the job done.</p>
         *
         * @param orig {@code null-ok;} the original spec
         * @return {@code null-ok;} an appropriately modified spec, or the
         * original if nothing needs to be done
         */
        private static RegisterSpec filterSpec(RegisterSpec orig) {
            if ((orig != null) && (orig.getType() == Type.KNOWN_NULL)) {
                return orig.withType(Type.OBJECT);
            }

            return orig;
        }

        /**
         * Adds an entry to the result, updating the adjunct tables
         * accordingly.
         *
         * @param address {@code >= 0;} the address
         * @param disposition {@code non-null;} the disposition
         * @param spec {@code non-null;} spec representing the local
         */
        private void add(int address, Disposition disposition,
                RegisterSpec spec) {
            int regNum = spec.getReg();

            result.add(new Entry(address, disposition, spec));

            if (disposition == Disposition.START) {
                regs.put(spec);
                endIndices[regNum] = -1;
            } else {
                regs.remove(spec);
                endIndices[regNum] = result.size() - 1;
            }
        }

        /**
         * Adds or updates an end local (changing its disposition). If
         * this would cause an empty range for a local, this instead
         * removes the local entirely.
         *
         * @param address {@code >= 0;} the address
         * @param disposition {@code non-null;} the disposition
         * @param spec {@code non-null;} spec representing the local
         */
        private void addOrUpdateEnd(int address, Disposition disposition,
                RegisterSpec spec) {
            if (disposition == Disposition.START) {
                throw new RuntimeException("shouldn't happen");
            }

            int regNum = spec.getReg();
            int endAt = endIndices[regNum];

            if (endAt >= 0) {
                // There is a previous end.
                Entry endEntry = result.get(endAt);
                if ((endEntry.getAddress() == address) &&
                        endEntry.getRegisterSpec().equals(spec)) {
                    /*
                     * The end is for the right address and variable, so
                     * update it.
                     */
                    result.set(endAt, endEntry.withDisposition(disposition));
                    regs.remove(spec); // TODO: Is this line superfluous?
                    return;
                }
            }

            endLocal(address, spec, disposition);
        }

        /**
         * Finishes processing altogether and gets the result.
         *
         * @return {@code non-null;} the result list
         */
        public LocalList finish() {
            aboutToProcess(Integer.MAX_VALUE, 0);

            int resultSz = result.size();
            int finalSz = resultSz - nullResultCount;

            if (finalSz == 0) {
                return EMPTY;
            }

            /*
             * Collect an array of only the non-null entries, and then
             * sort it to get a consistent order for everything: Local
             * ends and starts for a given address could come in any
             * order, but we want ends before starts as well as
             * registers in order (within ends or starts).
             */

            Entry[] resultArr = new Entry[finalSz];

            if (resultSz == finalSz) {
                result.toArray(resultArr);
            } else {
                int at = 0;
                for (Entry e : result) {
                    if (e != null) {
                        resultArr[at++] = e;
                    }
                }
            }

            Arrays.sort(resultArr);

            LocalList resultList = new LocalList(finalSz);

            for (int i = 0; i < finalSz; i++) {
                resultList.set(i, resultArr[i]);
            }

            resultList.setImmutable();
            return resultList;
        }
    }
}
