/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.netbeans.lib.v8debug;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import static org.netbeans.lib.v8debug.JSONConstants.*;
import org.netbeans.lib.v8debug.commands.Backtrace;
import org.netbeans.lib.v8debug.commands.ChangeBreakpoint;
import org.netbeans.lib.v8debug.commands.ChangeLive;
import org.netbeans.lib.v8debug.commands.ClearBreakpoint;
import org.netbeans.lib.v8debug.commands.ClearBreakpointGroup;
import org.netbeans.lib.v8debug.commands.Continue;
import org.netbeans.lib.v8debug.commands.Evaluate;
import org.netbeans.lib.v8debug.commands.Flags;
import org.netbeans.lib.v8debug.commands.Frame;
import org.netbeans.lib.v8debug.commands.GC;
import org.netbeans.lib.v8debug.commands.ListBreakpoints;
import org.netbeans.lib.v8debug.commands.Lookup;
import org.netbeans.lib.v8debug.commands.References;
import org.netbeans.lib.v8debug.commands.RestartFrame;
import org.netbeans.lib.v8debug.commands.Scope;
import org.netbeans.lib.v8debug.commands.Scopes;
import org.netbeans.lib.v8debug.commands.Scripts;
import org.netbeans.lib.v8debug.commands.SetBreakpoint;
import org.netbeans.lib.v8debug.commands.SetExceptionBreak;
import org.netbeans.lib.v8debug.commands.SetVariableValue;
import org.netbeans.lib.v8debug.commands.Source;
import org.netbeans.lib.v8debug.commands.Threads;
import org.netbeans.lib.v8debug.commands.V8Flags;
import org.netbeans.lib.v8debug.commands.Version;
import org.netbeans.lib.v8debug.events.AfterCompileEventBody;
import org.netbeans.lib.v8debug.events.BreakEventBody;
import org.netbeans.lib.v8debug.events.CompileErrorEventBody;
import org.netbeans.lib.v8debug.events.ExceptionEventBody;
import org.netbeans.lib.v8debug.events.ScriptCollectedEventBody;
import org.netbeans.lib.v8debug.vars.NewValue;
import org.netbeans.lib.v8debug.vars.ReferencedValue;
import org.netbeans.lib.v8debug.vars.V8Boolean;
import org.netbeans.lib.v8debug.vars.V8Function;
import org.netbeans.lib.v8debug.vars.V8Generator;
import org.netbeans.lib.v8debug.vars.V8Number;
import org.netbeans.lib.v8debug.vars.V8Object;
import org.netbeans.lib.v8debug.vars.V8ScriptValue;
import org.netbeans.lib.v8debug.vars.V8String;
import org.netbeans.lib.v8debug.vars.V8Value;

/**
 * Translator of JSON objects into the corresponding Java API classes.
 * 
 * @author Martin Entlicher
 */
public class JSONReader {

    private JSONReader() {}
    
    public static V8Type getType(JSONObject obj) throws IllegalArgumentException {
        String type = (String) obj.get(TYPE);
        if (type == null) {
            throw new IllegalArgumentException("No type in "+obj.toJSONString());
        }
        return V8Type.valueOf(type);
    }
    
    public static V8Response getResponse(JSONObject obj) throws IllegalArgumentException {
        long sequence = (Long) obj.get(SEQ);
        V8Type type = getType(obj);
        long requestSequence = (Long) obj.get(SEQ_REQUEST);
        String commandName = (String) obj.get(COMMAND);
        V8Command command = (commandName != null) ? V8Command.fromString(commandName) : null;
        Boolean runningObj = (Boolean) obj.get(RUNNING);
        boolean running = (runningObj != null) ? runningObj : false;
        boolean success = (Boolean) obj.get(SUCCESS);
        V8Body body = null;
        String errorMessage = null;
        if (success) {
            Object bodyObj = obj.get(BODY);
            if (bodyObj instanceof JSONObject) {
                body = getBody(command, (JSONObject) bodyObj);
            } else if (bodyObj instanceof JSONArray) {
                body = getBody(command, (JSONArray) bodyObj);
            } else if (body != null) {
                throw new IllegalArgumentException("Unknown body "+bodyObj+" in "+obj.toJSONString());
            }
        } else {
            errorMessage = (String) obj.get(MESSAGE);
        }
        ReferencedValue[] refs = getRefs((JSONArray) obj.get(REFS));
        return new V8Response(sequence, requestSequence, command, body, refs, running, success, errorMessage);
    }
    
    public static V8Event getEvent(JSONObject obj) throws IllegalArgumentException {
        long sequence = (Long) obj.get(SEQ);
        String eventName = (String) obj.get(EVENT);
        V8Event.Kind eventKind;
        V8Body body = null;
        if (eventName != null) {
            eventKind = V8Event.Kind.fromString(eventName);
            JSONObject bodyObj = (JSONObject) obj.get(BODY);
            switch (eventKind) {
                case AfterCompile:
                    V8Script script = getScript((JSONObject) bodyObj.get(EVT_SCRIPT));
                    body = new AfterCompileEventBody(script);
                    break;
                case CompileError:
                    script = getScript((JSONObject) bodyObj.get(EVT_SCRIPT));
                    body = new CompileErrorEventBody(script);
                    break;
                case ScriptCollected:
                    long scriptId = getLong((JSONObject) bodyObj.get(EVT_SCRIPT), ID);
                    body = new ScriptCollectedEventBody(scriptId);
                    break;
                case Break:
                    String invocationText = (String) bodyObj.get(EVT_INVOCATION_TEXT);
                    long sourceLine = getLong(bodyObj, EVT_SOURCE_LINE);
                    long sourceColumn = getLong(bodyObj, EVT_SOURCE_COLUMN);
                    String sourceLineText = (String) bodyObj.get(EVT_SOURCE_LINE_TEXT);
                    V8ScriptLocation scriptLocation = getScriptLocation((JSONObject) bodyObj.get(EVT_SCRIPT));
                    long[] breakpoints = getLongArray((JSONArray) bodyObj.get(EVT_BREAKPOINTS));
                    body = new BreakEventBody(invocationText, sourceLine, sourceColumn, sourceLineText, scriptLocation, breakpoints);
                    break;
                case Exception:
                    boolean uncaught = (boolean) bodyObj.get(EVT_UNCAUGHT);
                    V8Value exception = getValue((JSONObject) bodyObj.get(EVT_EXCEPTION));
                    sourceLine = getLong(bodyObj, EVT_SOURCE_LINE);
                    sourceColumn = getLong(bodyObj, EVT_SOURCE_COLUMN);
                    sourceLineText = (String) bodyObj.get(EVT_SOURCE_LINE_TEXT);
                    script = getScript((JSONObject) bodyObj.get(EVT_SCRIPT));
                    body = new ExceptionEventBody(uncaught, exception, sourceLine, sourceColumn, sourceLineText, script);
                    break;
                default:
                    new IllegalArgumentException("Unknown event "+eventName+" in "+obj.toJSONString()).printStackTrace();
            }
        } else {
            // Handle events like: {"seq":218,"type":"event","success":false,"message":"SyntaxError: Unexpected token C","running":false}
            eventKind = null;
        }
        ReferencedValue[] refs = getRefs((JSONArray) obj.get(REFS));
        Boolean running = (Boolean) obj.get(RUNNING);
        Boolean success = (Boolean) obj.get(SUCCESS);
        String errorMessage = (String) obj.get(MESSAGE);
        return new V8Event(sequence, eventKind, body, refs, running, success, errorMessage);
    }

    public static V8Request getRequest(JSONObject obj) {
        long sequence = (Long) obj.get(SEQ);
        V8Type type = getType(obj);
        if (V8Type.request != type) {
            throw new IllegalArgumentException("Expecting request type. Actual type = "+type);
        }
        String commandName = (String) obj.get(COMMAND);
        V8Command command = V8Command.fromString(commandName);
        JSONObject argsObj = (JSONObject) obj.get(ARGUMENTS);
        V8Arguments args;
        if (argsObj != null) {
            args = getArguments(command, argsObj);
        } else {
            args = getSpecialArguments(command, obj);
        }
        return new V8Request(sequence, command, args);
    }

    private static V8Body getBody(V8Command command, JSONObject obj) {
        switch (command) {
            case Listbreakpoints:
                V8Breakpoint[] breakpoints = getBreakpoints((JSONArray) obj.get(BREAK_POINTS));
                boolean breakOnExceptions = getBoolean(obj, BREAK_ON_EXCEPTIONS);
                boolean breakOnUncaughtExceptions = getBoolean(obj, BREAK_ON_UNCAUGHT_EXCEPTIONS);
                return new ListBreakpoints.ResponseBody(breakpoints, breakOnExceptions, breakOnUncaughtExceptions);
            case Setbreakpoint:
                String type = getString(obj, TYPE);
                long bpId = getLong(obj, BREAK_POINT);
                String scriptName = null;
                if ("scriptName".equals(type)) {
                    scriptName = getString(obj, SCRIPT_NAME);
                }
                Long line = getLongOrNull(obj, LINE);
                Long column = getLongOrNull(obj, COLUMN);
                V8Breakpoint.ActualLocation[] actualLocations = getActualLocations((JSONArray) obj.get(BREAK_ACTUAL_LOCATIONS));
                return new SetBreakpoint.ResponseBody(V8Breakpoint.Type.valueOf(type), bpId,
                                                      scriptName, line, column, actualLocations);
            case Setexceptionbreak:
                String typeName = getString(obj, TYPE);
                V8ExceptionBreakType extype = V8ExceptionBreakType.valueOf(typeName);
                if (extype == null) {
                    throw new IllegalArgumentException("Unknown exception breakpoint type: '"+typeName+"'.");
                }
                boolean enabled = getBoolean(obj, BREAK_ENABLED);
                return new SetExceptionBreak.ResponseBody(extype, enabled);
            case Clearbreakpoint:
                bpId = getLong(obj, BREAK_POINT);
                return new ClearBreakpoint.ResponseBody(bpId);
            case Clearbreakpointgroup:
                long[] bpIds = getLongArray((JSONArray) obj.get(BREAK_POINTS));
                return new ClearBreakpointGroup.ResponseBody(bpIds);
            case Backtrace:
                long fromFrame = getLong(obj, FROM_FRAME);
                long toFrame = getLong(obj, TO_FRAME);
                long totalFrames = getLong(obj, TOTAL_FRAMES);
                V8Frame[] frames = getFrames((JSONArray) obj.get(FRAMES));
                return new Backtrace.ResponseBody(fromFrame, toFrame, totalFrames, frames);
            case Frame:
                V8Frame frame = getFrame(obj);
                return new Frame.ResponseBody(frame);
            case Restartframe:
                JSONObject resultObj = (JSONObject) obj.get(RESULT);
                if (resultObj == null) {
                    return null;
                }
                return new RestartFrame.ResponseBody(resultObj);
            case Changelive:
                resultObj = (JSONObject) obj.get(RESULT);
                if (resultObj == null) {
                    return null;
                }
                ChangeLive.ChangeLog changeLog = getChangeLog((JSONArray) obj.get(CHANGE_LOG));
                ChangeLive.Result result = getChangeLiveResult(resultObj);
                Boolean stepInRecommended = getBooleanOrNull(obj, STEP_IN_RECOMMENDED);
                return new ChangeLive.ResponseBody(changeLog, result, stepInRecommended);
            case Lookup:
                Map<Long, V8Value> valuesByHandle = new LinkedHashMap<>();
                for (Object element : obj.values()) {
                    V8Value value = getValue((JSONObject) element);
                    valuesByHandle.put(value.getHandle(), value);
                }
                return new Lookup.ResponseBody(valuesByHandle);
            case Evaluate:
                V8Value value = getValue(obj);
                return new Evaluate.ResponseBody(value);
            case SetVariableValue:
                value = getValue((JSONObject) obj.get(NEW_VALUE));
                return new SetVariableValue.ResponseBody(value);
            case Scope:
                V8Scope scope = getScope(obj, null);
                return new Scope.ResponseBody(scope);
            case Scopes:
                long fromScope = getLong(obj, FROM_SCOPE);
                long toScope = getLong(obj, TO_SCOPE);
                long totalScopes = getLong(obj, TOTAL_SCOPES);
                V8Scope[] scopes = getScopes((JSONArray) obj.get(SCOPES), null);
                return new Scopes.ResponseBody(fromScope, toScope, totalScopes, scopes);
            case Source:
                String source = getString(obj, SOURCE);
                long fromLine = getLong(obj, FROM_LINE);
                long toLine = getLong(obj, TO_LINE);
                long fromPosition = getLong(obj, FROM_POSITION);
                long toPosition = getLong(obj, TO_POSITION);
                long totalLines = getLong(obj, TOTAL_LINES);
                return new Source.ResponseBody(source, fromLine, toLine, fromPosition, toPosition, totalLines);
            case Threads:
                long numThreads = getLong(obj, TOTAL_THREADS);
                Map<Long, Boolean> threads = getThreads((JSONArray) obj.get(THREADS));
                return new Threads.ResponseBody(numThreads, threads);
            case Gc:
                long before = getLong(obj, GC_BEFORE);
                long after = getLong(obj, GC_AFTER);
                return new GC.ResponseBody(before, after);
            case Version:
                String version = getString(obj, BODY_VERSION);
                return new Version.ResponseBody(version);
            case Flags:
                JSONArray flagsArray = (JSONArray) obj.get(FLAGS);
                Map<String, Boolean> flags = new LinkedHashMap<>();
                for (Object fObj : flagsArray) {
                    JSONObject flag = (JSONObject) fObj;
                    flags.put(getString(flag, NAME), getBoolean(flag, VALUE));
                }
                return new Flags.ResponseBody(flags);
            default:
                return null;
        }
    }

    private static V8Body getBody(V8Command command, JSONArray array) {
        switch (command) {
            case Scripts:
                int n = array.size();
                V8Script[] scripts = new V8Script[n];
                for (int i = 0; i < n; i++) {
                    scripts[i] = getScript((JSONObject) array.get(i));
                }
                return new Scripts.ResponseBody(scripts);
            case References:
                n = array.size();
                V8Value[] refs = new V8Value[n];
                for (int i = 0; i < n; i++) {
                    refs[i] = getValue((JSONObject) array.get(i));
                }
                return new References.ResponseBody(refs);
            default:
                return null;
        }
    }
    
    private static V8Arguments getArguments(V8Command command, JSONObject obj) {
        switch (command) {
            case Backtrace:
                return new Backtrace.Arguments(
                        getLongOrNull(obj, FROM_FRAME), getLongOrNull(obj, TO_FRAME),
                        getBooleanOrNull(obj, BOTTOM), getBooleanOrNull(obj, INLINE_REFS));
            case Changebreakpoint:
                return new ChangeBreakpoint.Arguments(
                        getLong(obj, BREAK_POINT), getBooleanOrNull(obj, BREAK_ENABLED),
                        getString(obj, BREAK_CONDITION), getLongOrNull(obj, BREAK_IGNORE_COUNT));
            case Changelive:
                return new ChangeLive.Arguments(
                        getLong(obj, SCRIPT_ID), getString(obj, NEW_SOURCE),
                        getBooleanOrNull(obj, PREVIEW_ONLY));
            case Clearbreakpoint:
                return new ClearBreakpoint.Arguments(getLong(obj, BREAK_POINT));
            case Clearbreakpointgroup:
                return new ClearBreakpointGroup.Arguments(getLong(obj, BREAK_GROUP_ID));
            case Continue:
                String step = getString(obj, ARGS_STEP_ACTION);
                if (step == null) {
                    return null;
                }
                return new Continue.Arguments(
                        V8StepAction.valueOf(step),
                        getLongOrNull(obj, ARGS_STEP_COUNT));
            case Evaluate:
                return new Evaluate.Arguments(
                        getString(obj, EVAL_EXPRESSION),
                        getLongOrNull(obj, FRAME),
                        getBooleanOrNull(obj, EVAL_GLOBAL),
                        getBooleanOrNull(obj, EVAL_DISABLE_BREAK),
                        getAdditionalContext(obj.get(EVAL_ADDITIONAL_CONTEXT)));
            case Flags:
                Object fobj = obj.get(FLAGS);
                if (!(fobj instanceof JSONArray)) {
                    return null;
                }
                JSONArray farray = (JSONArray) fobj;
                Map<String, Boolean> flags = new LinkedHashMap<>();
                for (int i = 0; i < farray.size(); i++) {
                    Object felm = farray.get(i);
                    if (felm instanceof JSONObject) {
                        JSONObject fo = (JSONObject) felm;
                        flags.put(getString(fo, NAME), getBooleanOrNull(fo, VALUE));
                    }
                }
                return new Flags.Arguments(flags);
            case Frame:
                return new Frame.Arguments(getLongOrNull(obj, NUMBER));
            case Gc:
                return new GC.Arguments(getString(obj, TYPE));
            case Lookup:
                long[] handles = null;
                Object hObj = obj.get(HANDLES);
                if (hObj instanceof JSONArray) {
                    handles = getLongArray((JSONArray) hObj);
                }
                return new Lookup.Arguments(handles, getBooleanOrNull(obj, INCLUDE_SOURCE));
            case References:
                References.Type rType;
                String rTypeStr = getString(obj, TYPE);
                if (rTypeStr != null) {
                    rType = References.Type.valueOf(rTypeStr);
                } else {
                    rType = null;
                }
                return new References.Arguments(rType, getLong(obj, HANDLE));
            case Restartframe:
                return new RestartFrame.Arguments(getLongOrNull(obj, FRAME));
            case Scope:
                return new Scope.Arguments(getLong(obj, NUMBER), getLongOrNull(obj, FRAME_NUMBER));
            case Scopes:
                return new Scopes.Arguments(getLongOrNull(obj, FRAME_NUMBER));
            case Scripts:
                V8Script.Types scrTypes = null;
                long types = getLong(obj, TYPES);
                if (types >= 0) {
                    scrTypes = new V8Script.Types((int) types);
                }
                long[] ids = null;
                Object idsObj = obj.get(IDs);
                if (idsObj instanceof JSONArray) {
                    ids = getLongArray((JSONArray) idsObj);
                }
                Boolean includeSource = getBooleanOrNull(obj, INCLUDE_SOURCE);
                Object filter = obj.get(FILTER);
                if (filter instanceof String) {
                    return new Scripts.Arguments(scrTypes, ids, includeSource, (String) filter);
                } else {
                    if (!(filter instanceof Long)) {
                        return null;
                    }
                    return new Scripts.Arguments(scrTypes, ids, includeSource, (Long) filter);
                }
            case SetVariableValue:
                Object nvObj = obj.get(NEW_VALUE);
                if (!(nvObj instanceof JSONObject)) {
                    return null;
                }
                NewValue nv;
                Long handle = getLongOrNull((JSONObject) nvObj, HANDLE);
                if (handle != null) {
                    nv = new NewValue(handle);
                } else {
                    Object typeObj = ((JSONObject) nvObj).get(TYPE);
                    if (!(typeObj instanceof String)) {
                        return null;
                    }
                    V8Value.Type type = V8Value.Type.fromString((String) typeObj);
                    nv = new NewValue(type, STRING_DESCRIPTION);
                }
                Object scopeObj = obj.get(SCOPE);
                if (!(scopeObj instanceof JSONObject)) {
                    return null;
                }
                return new SetVariableValue.Arguments(
                        getString(obj, NAME), nv,
                        getLong((JSONObject) scopeObj, NUMBER),
                        getLongOrNull((JSONObject) scopeObj, FRAME_NUMBER));
            case Setbreakpoint:
                Object bpTypeObj = obj.get(TYPE);
                if (!(bpTypeObj instanceof String)) {
                    return null;
                }
                String bpType = (String) bpTypeObj;
                if ("script".equals(bpType)) {
                    bpType = V8Breakpoint.Type.scriptName.toString();
                }
                return new SetBreakpoint.Arguments(
                        V8Breakpoint.Type.valueOf(bpType),
                        getString(obj, TARGET),
                        getLongOrNull(obj, LINE), getLongOrNull(obj, COLUMN),
                        getBooleanOrNull(obj, BREAK_ENABLED),
                        getString(obj, BREAK_CONDITION),
                        getLongOrNull(obj, BREAK_IGNORE_COUNT),
                        getLongOrNull(obj, BREAK_GROUP_ID));
            case Setexceptionbreak:
                bpTypeObj = obj.get(TYPE);
                if (!(bpTypeObj instanceof String)) {
                    return null;
                }
                bpType = (String) bpTypeObj;
                return new SetExceptionBreak.Arguments(
                        V8ExceptionBreakType.valueOf(bpType),
                        getBoolean(obj, BREAK_ENABLED));
            case Source:
                return new Source.Arguments(
                        getLongOrNull(obj, FRAME),
                        getLongOrNull(obj, FROM_LINE),
                        getLongOrNull(obj, TO_LINE));
            case V8flags:
                return new V8Flags.Arguments(getString(obj, FLAGS));
            default:
                return null;
        }
    }
    
    private static V8Arguments getSpecialArguments(V8Command command, JSONObject obj) {
        // Arguments that are directly on the command request:
        switch (command) {
            case Source:
                return new Source.Arguments(
                        getLongOrNull(obj, FRAME),
                        getLongOrNull(obj, FROM_LINE),
                        getLongOrNull(obj, TO_LINE));
            default:
                return null;
        }
    }
    
    private static Evaluate.Arguments.Context[] getAdditionalContext(Object obj) {
        if (!(obj instanceof JSONArray)) {
            return null;
        }
        JSONArray array = (JSONArray) obj;
        int n = array.size();
        Evaluate.Arguments.Context[] context = new Evaluate.Arguments.Context[n];
        for (int i = 0; i < n; i++) {
            context[i] = getContext(array.get(i));
        }
        return context;
    }
    
    private static Evaluate.Arguments.Context getContext(Object obj) {
        if (!(obj instanceof JSONObject)) {
            return null;
        }
        JSONObject jobj = (JSONObject) obj;
        return new Evaluate.Arguments.Context(getString(jobj, NAME),
                                              getLong(jobj, HANDLE));
    }
    
    /**
     * @return the String property value, or <code>null</code> when not defined.
     */
    private static String getString(JSONObject obj, String propertyName) {
        return (String) obj.get(propertyName);
    }
    
    private static String[] getStringValuesFromArray(JSONArray array, String propertyName) {
        int l = array.size();
        String[] strings = new String[l];
        for (int i = 0; i < l; i++) {
            strings[i] = getString((JSONObject) array.get(i), propertyName);
        }
        return strings;
    }
    
    /**
     * @return the long property value, or <code>-1</code> when not defined.
     */
    private static long getLong(JSONObject obj, String propertyName) {
        return getLong(obj, propertyName, -1);
    }
    
    /**
     * @return the long property value, or the defaultValue when not defined.
     */
    private static long getLong(JSONObject obj, String propertyName, long defaultValue) {
        Object prop = obj.get(propertyName);
        if (prop == null) {
            return defaultValue;
        }
        if (prop instanceof Long) {
            return (Long) prop;
        } else {
            String str = (String) prop;
            return Long.parseLong(str);
        }
    }
    
    private static Long getLongOrNull(JSONObject obj, String propertyName) {
        Object prop = obj.get(propertyName);
        if (prop == null) {
            return null;
        }
        return (Long) prop;
    }
    
    private static PropertyLong getLongProperty(JSONObject obj, String propertyName) {
        Object prop = obj.get(propertyName);
        if (prop == null) {
            return new PropertyLong(null);
        }
        if (prop instanceof Long) {
            return new PropertyLong((Long) prop);
        } else {
            String str = (String) prop;
            return new PropertyLong(Long.parseLong(str));
        }
    }
    
    /**
     * @return the boolean property value, or <code>false</code> when not defined.
     */
    private static boolean getBoolean(JSONObject obj, String propertyName) {
        Object prop = obj.get(propertyName);
        if (prop == null) {
            return false;
        }
        return (Boolean) prop;
    }
    
    private static Boolean getBooleanOrNull(JSONObject obj, String propertyName) {
        Object prop = obj.get(propertyName);
        if (prop == null) {
            return null;
        }
        return (Boolean) prop;
    }
    
    private static V8ScriptLocation getScriptLocation(JSONObject obj) {
        long id = getLong(obj, ID);
        String name = getString(obj, NAME);
        long line = getLong(obj, SCRIPT_LINE_OFFSET);
        long column = getLong(obj, SCRIPT_COLUMN_OFFSET);
        long lineCount = getLong(obj, SCRIPT_LINE_COUNT);
        return new V8ScriptLocation(id, name, line, column, lineCount);
    }
    
    private static V8Script getScript(JSONObject obj) {
        long handle = getLong(obj, HANDLE);
        String name = getString(obj, NAME);
        long id = getLong(obj, ID);
        long lineOffset = getLong(obj, SCRIPT_LINE_OFFSET);
        long columnOffset = getLong(obj, SCRIPT_COLUMN_OFFSET);
        long lineCount = getLong(obj, SCRIPT_LINE_COUNT);
        Object data = obj.get(DATA);
        String source = getString(obj, SOURCE);
        String sourceStart = getString(obj, SOURCE_START);
        Long sourceLength = getLongOrNull(obj, SOURCE_LENGTH);
        ReferencedValue context = getReferencedValue(obj, CONTEXT);
        String text = getString(obj, TEXT);
        long scriptTypeNum = getLong(obj, SCRIPT_TYPE);
        V8Script.Type scriptType = (scriptTypeNum >= 0) ? V8Script.Type.valueOf((int) scriptTypeNum) : null;
        long compilationTypeNum = getLong(obj, COMPILATION_TYPE);
        V8Script.CompilationType compilationType = (compilationTypeNum >= 0) ? V8Script.CompilationType.valueOf((int) compilationTypeNum) : null;
        ReferencedValue evalFromScript = getReferencedValue(obj, EVAL_FROM_SCRIPT);
        V8Script.EvalFromLocation evalFromLocation;
        if (V8Script.CompilationType.EVAL.equals(compilationType)) {
            evalFromLocation = new V8Script.EvalFromLocation(getLong(obj, LINE), getLong(obj, COLUMN));
        } else {
            evalFromLocation = null;
        }
        return new V8Script(handle, name, id, lineOffset, columnOffset, lineCount, data, source, sourceStart, sourceLength, context, text, scriptType, compilationType, evalFromScript, evalFromLocation);
    }

    private static V8Value getValue(JSONObject obj) {
        return getValue(obj, -1);
    }
    
    private static V8Value getValue(JSONObject obj, long handle) {
        if (handle < 0) {
            handle = getLong(obj, HANDLE);
        }
        V8Value.Type type = V8Value.Type.fromString(getString(obj, TYPE));
        String text = getString(obj, TEXT);
        switch (type) {
            case Boolean:
                return new V8Boolean(handle, getBoolean(obj, VALUE), text);
            case Number:
                Object nVal = obj.get(VALUE);
                if (nVal instanceof Long) {
                    return new V8Number(handle, (Long) nVal, text);
                }
                if (nVal instanceof Double) {
                    return new V8Number(handle, (Double) nVal, text);
                }
                if (nVal == null) {
                    return new V8Number(handle, -1l, text);
                }
                if (INFINITY.equals(nVal)) {
                    return new V8Number(handle, Double.POSITIVE_INFINITY, text);
                }
                if (("-"+INFINITY).equals(nVal)) {
                    return new V8Number(handle, Double.NEGATIVE_INFINITY, text);
                }
                if (NaN.equals(nVal)) {
                    return new V8Number(handle, Double.NaN, text);
                }
                throw new IllegalArgumentException("Unknown variable value type: "+nVal);
            case String:
                return new V8String(handle, getString(obj, VALUE), text);
            case Function:
                String name = getString(obj, NAME);
                String inferredName = getString(obj, FUNCTION_INFERRED_NAME);
                Boolean resolved = getBooleanOrNull(obj, FUNCTION_RESOLVED);
                String source = getString(obj, SOURCE);
                PropertyLong scriptRef = getReferenceProperty(obj, SCRIPT);
                Long scriptId = getLongOrNull(obj, SCRIPTID);
                PropertyLong position = getLongProperty(obj, POSITION);
                PropertyLong line = getLongProperty(obj, LINE);
                PropertyLong column = getLongProperty(obj, COLUMN);
                PropertyLong constructorFunctionHandle = getReferenceProperty(obj, VALUE_CONSTRUCTOR_FUNCTION);
                PropertyLong protoObject = getReferenceProperty(obj, VALUE_PROTO_OBJECT);
                PropertyLong prototypeObject = getReferenceProperty(obj, VALUE_PROTOTYPE_OBJECT);
                V8Scope[] scopes = null;
                if (obj.get(SCOPES) instanceof JSONArray) {
                    scopes = getScopes((JSONArray) obj.get(SCOPES), null);
                }
                Map<String, V8Object.Property> properties = getProperties((JSONArray) obj.get(VALUE_PROPERTIES), null);
                return new V8Function(handle, constructorFunctionHandle,
                                      protoObject, prototypeObject,
                                      name, inferredName, resolved,
                                      source, scriptRef, scriptId,
                                      position, line, column, scopes, properties, text);
            case Generator:
                String className = getString(obj, VALUE_CLASS_NAME);
                constructorFunctionHandle = getReferenceProperty(obj, VALUE_CONSTRUCTOR_FUNCTION);
                protoObject = getReferenceProperty(obj, VALUE_PROTO_OBJECT);
                prototypeObject = getReferenceProperty(obj, VALUE_PROTOTYPE_OBJECT);
                PropertyLong function = getReferenceProperty(obj, FRAME_FUNC);
                PropertyLong receiver = getReferenceProperty(obj, FRAME_RECEIVER);
                properties = getProperties((JSONArray) obj.get(VALUE_PROPERTIES), null);
                return new V8Generator(handle, className, constructorFunctionHandle, protoObject, prototypeObject, function, receiver, properties, text);
            case Object:
            case Error:
            case Regexp:
                className = getString(obj, VALUE_CLASS_NAME);
                constructorFunctionHandle = getReferenceProperty(obj, VALUE_CONSTRUCTOR_FUNCTION);
                protoObject = getReferenceProperty(obj, VALUE_PROTO_OBJECT);
                prototypeObject = getReferenceProperty(obj, VALUE_PROTOTYPE_OBJECT);
                V8Object.Array[] arrayRef;
                boolean isArray = "Array".equals(className);
                if (isArray) {
                    arrayRef = new V8Object.Array[] { null };
                } else {
                    arrayRef = null;
                }
                properties = getProperties((JSONArray) obj.get(VALUE_PROPERTIES), arrayRef);
                if (isArray && arrayRef[0] == null) {
                    arrayRef[0] = new V8Object.DefaultArray();
                }
                V8Object.Array array = (arrayRef != null) ? arrayRef[0] : null;
                return new V8Object(handle, type, className,
                                    constructorFunctionHandle,
                                    protoObject, prototypeObject,
                                    properties, array, text);
            case Frame:
                // ? TODO
                return new V8Value(handle, type, text);
            case Script:
                V8Script script = getScript(obj);
                return new V8ScriptValue(handle, script, text);
            default: // null, undefined
                return new V8Value(handle, type, text);
        }
    }

    private static long[] getLongArray(JSONArray array) {
        if (array == null) {
            return null;
        }
        int n = array.size();
        long[] iarr = new long[n];
        for (int i = 0; i < n; i++) {
            iarr[i] = (Long) array.get(i);
        }
        return iarr;
    }
    
    private static V8Breakpoint[] getBreakpoints(JSONArray array) {
        int n = array.size();
        V8Breakpoint[] breakpoints = new V8Breakpoint[n];
        for (int i = 0; i < n; i++) {
            breakpoints[i] = getBreakpoint((JSONObject) array.get(i));
        }
        return breakpoints;
    }

    private static V8Breakpoint getBreakpoint(JSONObject obj) {
        String typeStr = (String) obj.get(TYPE);
        /*if ("scriptName".equals(typeStr)) {
            typeStr = V8Breakpoint.Type.script.name();
        }*/
        V8Breakpoint.Type type = V8Breakpoint.Type.valueOf(typeStr);
        PropertyLong scriptId;
        String scriptName;
        if (V8Breakpoint.Type.scriptId.equals(type)) {
            scriptId = new PropertyLong(getLong(obj, SCRIPT_ID));
            scriptName = null;
        } else {
            scriptId = new PropertyLong(null);
            scriptName = getString(obj, SCRIPT_NAME);
        }
        long number = getLong(obj, NUMBER);
        PropertyLong line = getLongProperty(obj, LINE);
        PropertyLong column = getLongProperty(obj, COLUMN);
        PropertyLong groupId = getLongProperty(obj, BREAK_GROUP_ID);
        long hitCount = getLong(obj, BREAK_HIT_COUNT, 0);
        boolean active = getBoolean(obj, BREAK_ACTIVE);
        Object conditionObject = obj.get(BREAK_CONDITION);
        String condition;
        if (conditionObject instanceof String) {
            condition = (String) conditionObject;
        } else {
            condition = null;
        }
        long ignoreCount = getLong(obj, BREAK_IGNORE_COUNT, 0);
        V8Breakpoint.ActualLocation[] actualLocations = getActualLocations((JSONArray) obj.get(BREAK_ACTUAL_LOCATIONS));
        return new V8Breakpoint(type, scriptId, scriptName, number, line, column, groupId, hitCount, active, condition, ignoreCount, actualLocations);
    }
    
    private static V8Breakpoint.ActualLocation[] getActualLocations(JSONArray array) {
        int n = array.size();
        V8Breakpoint.ActualLocation[] locations = new V8Breakpoint.ActualLocation[n];
        for (int i = 0; i < n; i++) {
            JSONObject location = (JSONObject) array.get(i);
            long line = getLong(location, LINE);
            long column = getLong(location, COLUMN);
            String scriptName = getString(location, SCRIPT_NAME);
            if (scriptName != null) {
                locations[i] = new V8Breakpoint.ActualLocation(line, column, scriptName);
            } else {
                long scriptId = getLong(location, SCRIPT_ID);
                locations[i] = new V8Breakpoint.ActualLocation(line, column, scriptId);
            }
        }
        return locations;
    }
    
    private static V8Frame[] getFrames(JSONArray array) {
        if (array == null) {
            return new V8Frame[]{};
        }
        int n = array.size();
        V8Frame[] frames = new V8Frame[n];
        for (int i = 0; i < n; i++) {
            frames[i] = getFrame((JSONObject) array.get(i));
        }
        return frames;
    }
    
    private static V8Frame getFrame(JSONObject obj) {
        Long index = getLongOrNull(obj, INDEX);
        ReferencedValue receiver = getReferencedValue(obj, FRAME_RECEIVER);
        ReferencedValue func = getReferencedValue(obj, FRAME_FUNC);
        long scriptRef = getReference(obj, SCRIPT);
        boolean constructCall = getBoolean(obj, FRAME_CONSTRUCT_CALL);
        boolean atReturn = getBoolean(obj, FRAME_AT_RETURN);
        boolean debuggerFrame = getBoolean(obj, FRAME_DEBUGGER);
        Map<String, ReferencedValue> arguments = getReferences((JSONArray) obj.get(FRAME_ARGUMENTS));
        Map<String, ReferencedValue> locals = getReferences((JSONArray) obj.get(FRAME_LOCALS));
        long position = getLong(obj, POSITION);
        long line = getLong(obj, LINE);
        long column = getLong(obj, COLUMN);
        String sourceLineText = getString(obj, EVT_SOURCE_LINE_TEXT);
        V8Scope[] scopes = getScopes((JSONArray) obj.get(SCOPES), null);
        String text = getString(obj, TEXT);
        return new V8Frame(index, receiver, func, scriptRef, constructCall, atReturn,
                           debuggerFrame, arguments, locals, position, line, column,
                           sourceLineText, scopes, text);
    }
    
    private static Map<String, ReferencedValue> getReferences(JSONArray array) {
        if (array == null) {
            return null;
        }
        Map<String, ReferencedValue> references = new LinkedHashMap<>();
        for (Object obj : array) {
            String name = getString((JSONObject) obj, NAME);
            ReferencedValue ref = getReferencedValue((JSONObject) obj, VALUE);
            references.put(name, ref);
        }
        return references;
    }
    
    private static Map<String, V8Object.Property> getProperties(JSONArray array, V8Object.Array[] oArrayRef) {
        if (array == null) {
            return null;
        }
        if (array.isEmpty()) {
            return Collections.EMPTY_MAP;
        }
        Map<String, V8Object.Property> properties = new LinkedHashMap<>();
        V8Object.Property.Type[] types = V8Object.Property.Type.values();
        V8Object.DefaultArray oArray = null;
        for (Object obj : array) {
            JSONObject prop = (JSONObject) obj;
            Object nameObj = prop.get(NAME);
            if (nameObj == null) {
                continue;
            }
            //String name = getString(prop, NAME);
            long ref = getReference(prop);
            if (oArrayRef != null && nameObj instanceof Long) {
                // An array
                if (oArray == null) {
                    oArray = new V8Object.DefaultArray();
                }
                long index = (Long) nameObj;
                oArray.putReferenceAt(index, ref);
            } else {
                String name = nameObj.toString();
                long attributes = getLong(prop, ATTRIBUTES, 0);
                long propertyTypeNum = getLong(prop, PROPERTY_TYPE);
                V8Object.Property.Type type;
                if (propertyTypeNum < 0) {
                    type = null;
                } else if (propertyTypeNum < types.length) {
                    type = types[(int) propertyTypeNum];
                } else {
                    throw new IllegalArgumentException("Unknown property type: "+propertyTypeNum);
                }
                V8Object.Property property = new V8Object.Property(name, type, (int) attributes, ref);
                properties.put(name, property);
            }
        }
        if (oArrayRef != null) {
            oArrayRef[0] = oArray;
        }
        return properties;
    }
    
    private static ReferencedValue[] getRefs(JSONArray array) {
        if (array == null) {
            return null;
        }
        int n = array.size();
        ReferencedValue[] refs = new ReferencedValue[n];
        for (int i = 0; i < n; i++) {
            JSONObject obj = (JSONObject) array.get(i);
            long ref = getReference(obj);
            V8Value value = getValue(obj, ref);
            if (value != null) {
                refs[i] = new ReferencedValue(value.getHandle(), value);
            } else {
                refs[i] = new ReferencedValue(ref, value);
            }
        }
        return refs;
    }

    private static long getReference(JSONObject obj) {
        return getLong(obj, REF);
    }
    
    private static Long getReference(JSONObject obj, String propertyName) {
        JSONObject ref = (JSONObject) obj.get(propertyName);
        if (ref == null) {
            return null;
        }
        return getReference(ref);
    }
    
    private static PropertyLong getReferenceProperty(JSONObject obj, String propertyName) {
        JSONObject ref = (JSONObject) obj.get(propertyName);
        if (ref == null) {
            return new PropertyLong(null);
        }
        return getLongProperty(ref, REF);
    }
    
    private static ReferencedValue getReferencedValue(JSONObject obj, String propertyName) {
        JSONObject ref = (JSONObject) obj.get(propertyName);
        if (ref == null) {
            return null;
        }
        long reference = getReference(ref);
        V8Value value = null;
        if (getString(ref, TYPE) != null) {
            value = getValue(ref, reference);
        }
        return new ReferencedValue(reference, value);
    }
    
    private static V8Scope[] getScopes(JSONArray array, Long frameIndex) {
        int n = array.size();
        V8Scope[] scopes = new V8Scope[n];
        for (int i = 0; i < n; i++) {
            scopes[i] = getScope((JSONObject) array.get(i), frameIndex);
        }
        return scopes;
    }

    private static V8Scope getScope(JSONObject scope, Long frameIndex) {
        V8Scope.Type type = V8Scope.Type.valueOf((int) getLong(scope, TYPE));
        long index = getLong(scope, SCOPE_INDEX);
        PropertyLong scopeFrameIndex = getLongProperty(scope, FRAME_INDEX);
        if (!scopeFrameIndex.hasValue() && frameIndex != null) {
            scopeFrameIndex = new PropertyLong(frameIndex);
        }
        ReferencedValue referencedValue = getReferencedValue(scope, OBJECT);
        ReferencedValue<V8Object> referencedObject;
        if (referencedValue != null) {
            V8Object object = referencedValue.hasValue() ? (V8Object) referencedValue.getValue() : null;
            referencedObject = new ReferencedValue<>(referencedValue.getReference(), object);
        } else {
            referencedObject = null;
        }
        String text = getString(scope, TEXT);
        return new V8Scope(index, scopeFrameIndex, type, referencedObject, text);
    }
    
    private static Map<Long, Boolean> getThreads(JSONArray array) {
        Map<Long, Boolean> threads = new LinkedHashMap<>();
        for (Object o : array) {
            JSONObject obj = (JSONObject) o;
            threads.put(getLong(obj, ID), getBoolean(obj, CURRENT));
        }
        return threads;
    }
    
    private static ChangeLive.Result getChangeLiveResult(JSONObject resultObj) {
        ChangeLive.Result.ChangeTree changeTree = getChangeTree((JSONObject) resultObj.get(CHANGE_TREE));
        ChangeLive.Result.TextualDiff diff = getTextualDiff((JSONObject) resultObj.get(TEXTUAL_DIFF));
        boolean updated = getBoolean(resultObj, UPDATED);
        Boolean stackModified = getBooleanOrNull(resultObj, STACK_MODIFIED);
        Boolean stackUpdateNeedsStepIn = getBooleanOrNull(resultObj, STACK_UPDATE_NEEDS_STEP_IN);
        String createdScriptName = getString(resultObj, CREATED_SCRIPT_NAME);
        return new ChangeLive.Result(changeTree, diff, updated, stackModified, stackUpdateNeedsStepIn, createdScriptName);
    }

    private static ChangeLive.Result.ChangeTree getChangeTree(JSONObject obj) {
        String name = getString(obj, NAME);
        ChangeLive.Result.ChangeTree.Positions positions = getChangeTreePositions((JSONObject) obj.get(POSITIONS));
        ChangeLive.Result.ChangeTree.Positions newPositions = getChangeTreePositions((JSONObject) obj.get(NEW_POSITIONS));
        ChangeLive.Result.ChangeTree.FunctionStatus status;
        String statusStr = getString(obj, STATUS);
        if (statusStr != null) {
            status = ChangeLive.Result.ChangeTree.FunctionStatus.fromString(statusStr);
        } else {
            status = null;
        }
        String statusExplanation = getString(obj, STATUS_EXPLANATION);
        ChangeLive.Result.ChangeTree[] children = getChangeTreeChildren((JSONArray) obj.get(CHILDREN));
        ChangeLive.Result.ChangeTree[] newChildren = getChangeTreeChildren((JSONArray) obj.get(NEW_CHILDREN));
        return new ChangeLive.Result.ChangeTree(name, positions, newPositions, status, statusExplanation, children, newChildren);
    }
    
    private static ChangeLive.Result.ChangeTree[] getChangeTreeChildren(JSONArray array) {
        if (array == null) {
            return null;
        }
        int n = array.size();
        ChangeLive.Result.ChangeTree[] ch = new ChangeLive.Result.ChangeTree[n];
        for (int i = 0; i < n; i++) {
            ch[i] = getChangeTree((JSONObject) array.get(i));
        }
        return ch;
    }

    private static ChangeLive.Result.TextualDiff getTextualDiff(JSONObject obj) {
        long oldLen = getLong(obj, OLD_LEN);
        long newLen = getLong(obj, NEW_LEN);
        long[] chunks = getLongArray((JSONArray) obj.get(CHUNKS));
        return new ChangeLive.Result.TextualDiff(oldLen, newLen, chunks);
    }
    
    private static ChangeLive.Result.ChangeTree.Positions getChangeTreePositions(JSONObject obj) {
        if (obj == null) {
            return null;
        }
        long startPosition = getLong(obj, START_POSITION);
        long endPosition = getLong(obj, END_POSITION);
        return new ChangeLive.Result.ChangeTree.Positions(startPosition, endPosition);
    }

    private static ChangeLive.ChangeLog getChangeLog(JSONArray array) {
        int n = array.size();
        if (n == 0) {
            return null;
        }
        ChangeLive.ChangeLog.BreakpointUpdate[] breakpointsUpdate = null;
        String[] namesLinkedToOldScript = null;
        String[] droppedFrames = null;
        ChangeLive.ChangeLog.FunctionPatched functionPatched = null;
        ChangeLive.ChangeLog.PositionPatched[] patchedPositions = null;
        for (Object aelem : array) {
            if (!(aelem instanceof JSONObject)) {
                continue;
            }
            JSONObject obj = (JSONObject) aelem;
            JSONArray breakpointsUpdateArr = (JSONArray) obj.get(BREAK_POINTS_UPDATE);
            if (breakpointsUpdateArr != null) {
                breakpointsUpdate = getChangeLogBreakpointsUpdate(breakpointsUpdateArr);
            }
            JSONArray linkedToOldScriptArr = (JSONArray) obj.get(LINKED_TO_OLD_SCRIPT);
            if (linkedToOldScriptArr != null) {
                namesLinkedToOldScript = getStringValuesFromArray(linkedToOldScriptArr, NAME);
            }
            JSONArray droppedFromStack = (JSONArray) obj.get(DROPPED_FROM_STACK);
            if (droppedFromStack != null) {
                droppedFrames = getStringValuesFromArray(droppedFromStack, NAME);
            }
            String fp = (String) obj.get(FUNCTION_PATCHED);
            if (fp != null) {
                Boolean finf = getBooleanOrNull(obj, FUNCTION_INFO_NOT_FOUND);
                functionPatched = new ChangeLive.ChangeLog.FunctionPatched(fp, new PropertyBoolean(finf));
            }
            JSONArray positionPatchedArr = (JSONArray) obj.get(POSITION_PATCHED);
            if (positionPatchedArr != null) {
                patchedPositions = getPatchedPositions(positionPatchedArr);
            }
        }
        return new ChangeLive.ChangeLog(breakpointsUpdate, namesLinkedToOldScript,
                                        droppedFrames, functionPatched, patchedPositions);
    }
    
    private static ChangeLive.ChangeLog.BreakpointUpdate[] getChangeLogBreakpointsUpdate(JSONArray array) {
        int l = array.size();
        ChangeLive.ChangeLog.BreakpointUpdate[] bpus = new ChangeLive.ChangeLog.BreakpointUpdate[l];
        for (int i = 0; i < l; i++) {
            JSONObject bpu = (JSONObject) array.get(i);
            String typeRaw = getString(bpu, TYPE);
            ChangeLive.ChangeLog.BreakpointUpdate.Type type =
                    ChangeLive.ChangeLog.BreakpointUpdate.Type.fromString(typeRaw);
            long id = getLong(bpu, ID);
            PropertyLong newId = getLongProperty(bpu, NEW_ID);
            ChangeLive.ChangeLog.BreakpointUpdate.Position oldPositions = null;
            ChangeLive.ChangeLog.BreakpointUpdate.Position newPositions = null;
            JSONObject positionsObj = (JSONObject) bpu.get(OLD_POSITIONS);
            if (positionsObj != null) {
                oldPositions = getPositions(positionsObj);
            }
            positionsObj = (JSONObject) bpu.get(POSITIONS);
            if (positionsObj == null) {
                positionsObj = (JSONObject) bpu.get(NEW_POSITIONS);
            }
            if (positionsObj != null) {
                newPositions = getPositions(positionsObj);
            }
            bpus[i] = new ChangeLive.ChangeLog.BreakpointUpdate(type, id, newId,
                                                                oldPositions, newPositions);
        }
        return bpus;
    }
    
    private static ChangeLive.ChangeLog.BreakpointUpdate.Position getPositions(JSONObject positionObj) {
        long position = getLong(positionObj, POSITION);
        long line = getLong(positionObj, LINE);
        long column = getLong(positionObj, COLUMN);
        return new ChangeLive.ChangeLog.BreakpointUpdate.Position(position, line, column);
    }
    
    private static ChangeLive.ChangeLog.PositionPatched[] getPatchedPositions(JSONArray array) {
        int l = array.size();
        ChangeLive.ChangeLog.PositionPatched[] pps = new ChangeLive.ChangeLog.PositionPatched[l];
        for (int i = 0; i < l; i++) {
            JSONObject pp = (JSONObject) array.get(i);
            String name = getString(pp, NAME);
            Boolean infoNF = getBooleanOrNull(pp, INFO_NOT_FOUND);
            pps[i] = new ChangeLive.ChangeLog.PositionPatched(name, new PropertyBoolean(infoNF));
        }
        return pps;
    }

}
