/*
 * Copyright (c) 2004, 2012, Oracle and/or its affiliates. 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.
 *
 * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.utilities.soql;

import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;

public class JSJavaFrame extends DefaultScriptObject {
    private static final int FIELD_METHOD      = 0;
    private static final int FIELD_BCI         = 1;
    private static final int FIELD_LINE_NUMBER = 2;
    private static final int FIELD_LOCALS      = 3;
    private static final int FIELD_THIS_OBJECT = 4;
    private static final int FIELD_THREAD      = 5;
    private static final int FIELD_UNDEFINED   = -1;

    public JSJavaFrame(JavaVFrame jvf, JSJavaFactory fac) {
        this.jvf = jvf;
        this.factory = fac;
    }

    public Object get(String name) {
        int fieldID = getFieldID(name);
        switch (fieldID) {
        case FIELD_METHOD:
            return getMethod();
        case FIELD_BCI:
            return new Integer(getBCI());
        case FIELD_LINE_NUMBER:
            return new Integer(getLineNumber());
        case FIELD_LOCALS:
            return getLocals();
        case FIELD_THIS_OBJECT:
            return getThisObject();
        case FIELD_THREAD:
            return getThread();
        case FIELD_UNDEFINED:
        default:
            return super.get(name);
        }
    }

    public Object[] getIds() {
       Object[] fieldNames = fields.keySet().toArray();
       Object[] superFields = super.getIds();
       Object[] res = new Object[fieldNames.length + superFields.length];
       System.arraycopy(fieldNames, 0, res, 0, fieldNames.length);
       System.arraycopy(superFields, 0, res, fieldNames.length, superFields.length);
       return res;
   }

    public boolean has(String name) {
        if (getFieldID(name) != FIELD_UNDEFINED) {
            return true;
        } else {
            return super.has(name);
        }
    }

    public void put(String name, Object value) {
        if (getFieldID(name) == FIELD_UNDEFINED) {
            super.put(name, value);
        }
    }

    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append("Frame (method=");
        buf.append(jvf.getMethod().externalNameAndSignature());
        buf.append(", bci=");
        buf.append(getBCI());
        buf.append(", line=");
        buf.append(getLineNumber());
        buf.append(')');
        return buf.toString();
    }

    //-- Internals only below this point
    private static Map fields = new HashMap();
    private static void addField(String name, int fieldId) {
        fields.put(name, new Integer(fieldId));
    }

    private static int getFieldID(String name) {
        Integer res = (Integer) fields.get(name);
        return (res != null)? res.intValue() : FIELD_UNDEFINED;
    }

    static {
        addField("method", FIELD_METHOD);
        addField("bci", FIELD_BCI);
        addField("line", FIELD_LINE_NUMBER);
        addField("locals", FIELD_LOCALS);
        addField("thisObject", FIELD_THIS_OBJECT);
        addField("thread", FIELD_THREAD);
    }

    private JSJavaMethod getMethod() {
        return factory.newJSJavaMethod(jvf.getMethod());
    }

    private int getBCI() {
        return jvf.getBCI();
    }

    private int getLineNumber() {
        int bci = jvf.getBCI();
        if (bci == -1) {
            return 0;
        } else {
            int lineNum = jvf.getMethod().getLineNumberFromBCI(bci);
            return (lineNum <= 0)? 0 : lineNum;
        }
    }

    private synchronized JSMap getLocals() {
        if (localsCache == null) {
            Map map = new HashMap();
            localsCache = factory.newJSMap(map);
            StackValueCollection values = jvf.getLocals();
            Method method = jvf.getMethod();
            if (method.isNative() || ! method.hasLocalVariableTable() ||
                values == null) {
                return localsCache;
            }

            LocalVariableTableElement[] localVars = method.getLocalVariableTable();
            int bci = getBCI();
            List visibleVars = new ArrayList(0);
            for (int i = 0; i < localVars.length; i++) {
                LocalVariableTableElement cur = localVars[i];
                int startBCI = cur.getStartBCI();
                if (startBCI <= bci && bci < startBCI + cur.getLength()) {
                    visibleVars.add(cur);
                }
            }

            OopHandle handle = null;
            ObjectHeap heap = VM.getVM().getObjectHeap();
            for (Iterator varItr = visibleVars.iterator(); varItr.hasNext();) {
                LocalVariableTableElement cur = (LocalVariableTableElement) varItr.next();
                String name =  method.getConstants().getSymbolAt(cur.getNameCPIndex()).asString();
                int slot = cur.getSlot();

                String signature = method.getConstants().getSymbolAt(cur.getDescriptorCPIndex()).asString();
                BasicType variableType = BasicType.charToBasicType(signature.charAt(0));
                Object value = null;
                if (variableType == BasicType.T_BOOLEAN) {
                    value = Boolean.valueOf(values.booleanAt(slot));
                } else if (variableType == BasicType.T_CHAR) {
                    value = new Character(values.charAt(slot));
                } else if (variableType == BasicType.T_FLOAT) {
                    value = new Float(values.floatAt(slot));
                } else if (variableType == BasicType.T_DOUBLE) {
                    value = new Double(values.doubleAt(slot));
                } else if (variableType == BasicType.T_BYTE) {
                    value = new Byte(values.byteAt(slot));
                } else if (variableType == BasicType.T_SHORT) {
                    value = new Short(values.shortAt(slot));
                } else if (variableType == BasicType.T_INT) {
                    value = new Integer(values.intAt(slot));
                } else if (variableType == BasicType.T_LONG) {
                    value = new Long(values.longAt(slot));
                } else if (variableType == BasicType.T_OBJECT ||
                       variableType == BasicType.T_ARRAY) {
                    handle = values.oopHandleAt(slot);
                    value = factory.newJSJavaObject(heap.newOop(handle));
                } else {
                    // ignore
                }
                map.put(name, value);
            }
        }
        return localsCache;
    }

    private JSJavaObject getThisObject() {
        Method method = jvf.getMethod();
        if (method.isStatic()) {
            return null;
        }
        StackValueCollection values = jvf.getLocals();
        if (values != null) {
            // 'this' at index 0.
            OopHandle handle = values.oopHandleAt(0);
            ObjectHeap heap = VM.getVM().getObjectHeap();
            return factory.newJSJavaObject(heap.newOop(handle));
        } else {
            // can't get locals, return null.
            return null;
        }
    }

    private JSJavaThread getThread() {
        return factory.newJSJavaThread(jvf.getThread());
    }

    private final JavaVFrame jvf;
    private final JSJavaFactory factory;
    private JSMap localsCache;
}
