/*
 * Copyright 1998-2005 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.tools.jdi;

import com.sun.jdi.*;

import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Collections;

public class StackFrameImpl extends MirrorImpl
                            implements StackFrame, ThreadListener
{
    /* Once false, frame should not be used.
     * access synchronized on (vm.state())
     */
    private boolean isValid = true;

    private final ThreadReferenceImpl thread;
    private final long id;
    private final Location location;
    private Map<String, LocalVariable> visibleVariables =  null;
    private ObjectReference thisObject = null;

    StackFrameImpl(VirtualMachine vm, ThreadReferenceImpl thread,
                   long id, Location location) {
        super(vm);
        this.thread = thread;
        this.id = id;
        this.location = location;
        thread.addListener(this);
    }

    /*
     * ThreadListener implementation
     * Must be synchronized since we must protect against
     * sending defunct (isValid == false) stack ids to the back-end.
     */
    public boolean threadResumable(ThreadAction action) {
        synchronized (vm.state()) {
            if (isValid) {
                isValid = false;
                return false;   /* remove this stack frame as a listener */
            } else {
                throw new InternalException(
                                  "Invalid stack frame thread listener");
            }
        }
    }

    void validateStackFrame() {
        if (!isValid) {
            throw new InvalidStackFrameException("Thread has been resumed");
        }
    }

    /**
     * Return the frame location.
     * Need not be synchronized since it cannot be provably stale.
     */
    public Location location() {
        validateStackFrame();
        return location;
    }

    /**
     * Return the thread holding the frame.
     * Need not be synchronized since it cannot be provably stale.
     */
    public ThreadReference thread() {
        validateStackFrame();
        return thread;
    }

    public boolean equals(Object obj) {
        if ((obj != null) && (obj instanceof StackFrameImpl)) {
            StackFrameImpl other = (StackFrameImpl)obj;
            return (id == other.id) &&
                   (thread().equals(other.thread())) &&
                   (location().equals(other.location())) &&
                    super.equals(obj);
        } else {
            return false;
        }
    }

    public int hashCode() {
        return (thread().hashCode() << 4) + ((int)id);
    }

    public ObjectReference thisObject() {
        validateStackFrame();
        MethodImpl currentMethod = (MethodImpl)location.method();
        if (currentMethod.isStatic() || currentMethod.isNative()) {
            return null;
        } else {
            if (thisObject == null) {
                PacketStream ps;

                /* protect against defunct frame id */
                synchronized (vm.state()) {
                    validateStackFrame();
                    ps = JDWP.StackFrame.ThisObject.
                                      enqueueCommand(vm, thread, id);
                }

                /* actually get it, now that order is guaranteed */
                try {
                    thisObject = JDWP.StackFrame.ThisObject.
                                      waitForReply(vm, ps).objectThis;
                } catch (JDWPException exc) {
                    switch (exc.errorCode()) {
                    case JDWP.Error.INVALID_FRAMEID:
                    case JDWP.Error.THREAD_NOT_SUSPENDED:
                    case JDWP.Error.INVALID_THREAD:
                        throw new InvalidStackFrameException();
                    default:
                        throw exc.toJDIException();
                    }
                }
            }
        }
        return thisObject;
    }

    /**
     * Build the visible variable map.
     * Need not be synchronized since it cannot be provably stale.
     */
    private void createVisibleVariables() throws AbsentInformationException {
        if (visibleVariables == null) {
            List<LocalVariable> allVariables = location.method().variables();
            Map<String, LocalVariable> map = new HashMap<String, LocalVariable>(allVariables.size());

            for (LocalVariable variable : allVariables) {
                String name = variable.name();
                if (variable.isVisible(this)) {
                    LocalVariable existing = (LocalVariable)map.get(name);
                    if ((existing == null) ||
                        ((LocalVariableImpl)variable).hides(existing)) {
                        map.put(name, variable);
                    }
                }
            }
            visibleVariables = map;
        }
    }

    /**
     * Return the list of visible variable in the frame.
     * Need not be synchronized since it cannot be provably stale.
     */
    public List<LocalVariable> visibleVariables() throws AbsentInformationException {
        validateStackFrame();
        createVisibleVariables();
        List<LocalVariable> mapAsList = new ArrayList<LocalVariable>(visibleVariables.values());
        Collections.sort(mapAsList);
        return mapAsList;
    }

    /**
     * Return a particular variable in the frame.
     * Need not be synchronized since it cannot be provably stale.
     */
    public LocalVariable visibleVariableByName(String name) throws AbsentInformationException  {
        validateStackFrame();
        createVisibleVariables();
        return visibleVariables.get(name);
    }

    public Value getValue(LocalVariable variable) {
        List<LocalVariable> list = new ArrayList<LocalVariable>(1);
        list.add(variable);
        return getValues(list).get(variable);
    }

    public Map<LocalVariable, Value> getValues(List<? extends LocalVariable> variables) {
        validateStackFrame();
        validateMirrors(variables);

        int count = variables.size();
        JDWP.StackFrame.GetValues.SlotInfo[] slots =
                           new JDWP.StackFrame.GetValues.SlotInfo[count];

        for (int i=0; i<count; ++i) {
            LocalVariableImpl variable = (LocalVariableImpl)variables.get(i);
            if (!variable.isVisible(this)) {
                throw new IllegalArgumentException(variable.name() +
                                 " is not valid at this frame location");
            }
            slots[i] = new JDWP.StackFrame.GetValues.SlotInfo(variable.slot(),
                                      (byte)variable.signature().charAt(0));
        }

        PacketStream ps;

        /* protect against defunct frame id */
        synchronized (vm.state()) {
            validateStackFrame();
            ps = JDWP.StackFrame.GetValues.enqueueCommand(vm, thread, id, slots);
        }

        /* actually get it, now that order is guaranteed */
        ValueImpl[] values;
        try {
            values = JDWP.StackFrame.GetValues.waitForReply(vm, ps).values;
        } catch (JDWPException exc) {
            switch (exc.errorCode()) {
                case JDWP.Error.INVALID_FRAMEID:
                case JDWP.Error.THREAD_NOT_SUSPENDED:
                case JDWP.Error.INVALID_THREAD:
                    throw new InvalidStackFrameException();
                default:
                    throw exc.toJDIException();
            }
        }

        if (count != values.length) {
            throw new InternalException(
                      "Wrong number of values returned from target VM");
        }
        Map<LocalVariable, Value> map = new HashMap<LocalVariable, Value>(count);
        for (int i=0; i<count; ++i) {
            LocalVariableImpl variable = (LocalVariableImpl)variables.get(i);
            map.put(variable, values[i]);
        }
        return map;
    }

    public void setValue(LocalVariable variableIntf, Value valueIntf)
        throws InvalidTypeException, ClassNotLoadedException {

        validateStackFrame();
        validateMirror(variableIntf);
        validateMirrorOrNull(valueIntf);

        LocalVariableImpl variable = (LocalVariableImpl)variableIntf;
        ValueImpl value = (ValueImpl)valueIntf;

        if (!variable.isVisible(this)) {
            throw new IllegalArgumentException(variable.name() +
                             " is not valid at this frame location");
        }

        try {
            // Validate and convert value if necessary
            value = ValueImpl.prepareForAssignment(value, variable);

            JDWP.StackFrame.SetValues.SlotInfo[] slotVals =
                new JDWP.StackFrame.SetValues.SlotInfo[1];
            slotVals[0] = new JDWP.StackFrame.SetValues.
                                       SlotInfo(variable.slot(), value);

            PacketStream ps;

            /* protect against defunct frame id */
            synchronized (vm.state()) {
                validateStackFrame();
                ps = JDWP.StackFrame.SetValues.
                                     enqueueCommand(vm, thread, id, slotVals);
            }

            /* actually set it, now that order is guaranteed */
            try {
                JDWP.StackFrame.SetValues.waitForReply(vm, ps);
            } catch (JDWPException exc) {
                switch (exc.errorCode()) {
                case JDWP.Error.INVALID_FRAMEID:
                case JDWP.Error.THREAD_NOT_SUSPENDED:
                case JDWP.Error.INVALID_THREAD:
                    throw new InvalidStackFrameException();
                default:
                    throw exc.toJDIException();
                }
            }
        } catch (ClassNotLoadedException e) {
            /*
             * Since we got this exception,
             * the variable type must be a reference type. The value
             * we're trying to set is null, but if the variable's
             * class has not yet been loaded through the enclosing
             * class loader, then setting to null is essentially a
             * no-op, and we should allow it without an exception.
             */
            if (value != null) {
                throw e;
            }
        }
    }

    public List<Value> getArgumentValues() {
        validateStackFrame();
        MethodImpl mmm = (MethodImpl)location.method();
        List<String> argSigs = mmm.argumentSignatures();
        int count = argSigs.size();
        JDWP.StackFrame.GetValues.SlotInfo[] slots =
                           new JDWP.StackFrame.GetValues.SlotInfo[count];

        int slot;
        if (mmm.isStatic()) {
            slot = 0;
        } else {
            slot = 1;
        }
        for (int ii = 0; ii < count; ++ii) {
            char sigChar =  (char)argSigs.get(ii).charAt(0);
            slots[ii] = new JDWP.StackFrame.GetValues.SlotInfo(slot++,(byte)sigChar);
            if (sigChar == 'J' || sigChar == 'D') {
                slot++;
            }
        }

        PacketStream ps;

        /* protect against defunct frame id */
        synchronized (vm.state()) {
            validateStackFrame();
            ps = JDWP.StackFrame.GetValues.enqueueCommand(vm, thread, id, slots);
        }

        ValueImpl[] values;
        try {
            values = JDWP.StackFrame.GetValues.waitForReply(vm, ps).values;
        } catch (JDWPException exc) {
            switch (exc.errorCode()) {
                case JDWP.Error.INVALID_FRAMEID:
                case JDWP.Error.THREAD_NOT_SUSPENDED:
                case JDWP.Error.INVALID_THREAD:
                    throw new InvalidStackFrameException();
                default:
                    throw exc.toJDIException();
            }
        }

        if (count != values.length) {
            throw new InternalException(
                      "Wrong number of values returned from target VM");
        }
        return Arrays.asList((Value[])values);
    }

    void pop() throws IncompatibleThreadStateException {
        validateStackFrame();
        // flush caches and disable caching until command completion
        CommandSender sender =
            new CommandSender() {
                public PacketStream send() {
                    return JDWP.StackFrame.PopFrames.enqueueCommand(vm,
                                 thread, id);
                }
        };
        try {
            PacketStream stream = thread.sendResumingCommand(sender);
            JDWP.StackFrame.PopFrames.waitForReply(vm, stream);
        } catch (JDWPException exc) {
            switch (exc.errorCode()) {
            case JDWP.Error.THREAD_NOT_SUSPENDED:
                throw new IncompatibleThreadStateException(
                         "Thread not current or suspended");
            case JDWP.Error.INVALID_THREAD:   /* zombie */
                throw new IncompatibleThreadStateException("zombie");
            case JDWP.Error.NO_MORE_FRAMES:
                throw new InvalidStackFrameException(
                         "No more frames on the stack");
            default:
                throw exc.toJDIException();
            }
        }

        // enable caching - suspended again
        vm.state().freeze();
    }

    public String toString() {
       return location.toString() + " in thread " + thread.toString();
    }
}
