/*
 * 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.Map;
import org.json.simple.JSONArray;
import org.json.simple.JSONAware;
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.connection.LinkedJSONObject;
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 Java API classes into the corresponding JSON objects.
 * 
 * @author Martin Entlicher
 */
@SuppressWarnings("unchecked")
public class JSONWriter {
    
    private JSONWriter() {}
    
    public static JSONObject store(V8Request request) {
        JSONObject obj = newJSONObject();
        obj.put(SEQ, request.getSequence());
        obj.put(TYPE, V8Type.request.toString());
        V8Command command = request.getCommand();
        obj.put(COMMAND, command.toString());
        V8Arguments arguments = request.getArguments();
        if (arguments != null) {
            obj.put(ARGUMENTS, store(command, arguments));
        }
        return obj;
    }
    
    public static JSONObject store(V8Response response) {
        JSONObject obj = newJSONObject();
        obj.put(SEQ, response.getSequence());
        obj.put(SEQ_REQUEST, response.getRequestSequence());
        obj.put(TYPE, V8Type.response.toString());
        V8Command command = response.getCommand();
        obj.put(COMMAND, command.toString());
        boolean success = response.isSuccess();
        obj.put(SUCCESS, success);
        if (success) {
            V8Body body = response.getBody();
            if (body != null) {
                obj.put(BODY, store(command, body));
            }
        } else {
            obj.put(MESSAGE, response.getErrorMessage());
        }
        ReferencedValue[] referencedValues = response.getReferencedValues();
        if (referencedValues != null) {
            obj.put(REFS, store(referencedValues));
        }
        obj.put(RUNNING, response.isRunning());
        return obj;
    }
    
    public static JSONObject store(V8Event event) {
        JSONObject obj = newJSONObject();
        obj.put(SEQ, event.getSequence());
        obj.put(TYPE, V8Type.event.toString());
        V8Event.Kind eventKind = event.getKind();
        obj.put(EVENT, eventKind.toString());
        V8Body body = event.getBody();
        JSONObject bodyObj = newJSONObject();
        switch (eventKind) {
            case AfterCompile:
                AfterCompileEventBody aceb = (AfterCompileEventBody) body;
                bodyObj.put(EVT_SCRIPT, store(aceb.getScript()));
                break;
            case CompileError:
                CompileErrorEventBody ceeb = (CompileErrorEventBody) body;
                bodyObj.put(EVT_SCRIPT, store(ceeb.getScript()));
                break;
            case ScriptCollected:
                ScriptCollectedEventBody sceb = (ScriptCollectedEventBody) body;
                bodyObj.put(EVT_SCRIPT, sceb.getScriptId());
                break;
            case Break:
                BreakEventBody beb = (BreakEventBody) body;
                storeIf(beb.getInvocationText(), bodyObj, EVT_INVOCATION_TEXT);
                bodyObj.put(EVT_SOURCE_LINE, beb.getSourceLine());
                bodyObj.put(EVT_SOURCE_COLUMN, beb.getSourceColumn());
                storeIf(beb.getSourceLineText(), bodyObj, EVT_SOURCE_LINE_TEXT);
                V8ScriptLocation scriptLocation = beb.getScript();
                if (scriptLocation != null) {
                    bodyObj.put(EVT_SCRIPT, store(scriptLocation));
                }
                long[] breakpoints = beb.getBreakpoints();
                if (breakpoints != null) {
                    bodyObj.put(EVT_BREAKPOINTS, array(breakpoints));
                }
                break;
            case Exception:
                ExceptionEventBody eeb = (ExceptionEventBody) body;
                bodyObj.put(EVT_UNCAUGHT, eeb.isUncaught());
                bodyObj.put(EVT_EXCEPTION, store(eeb.getException()));
                bodyObj.put(EVT_SOURCE_LINE, eeb.getSourceLine());
                bodyObj.put(EVT_SOURCE_COLUMN, eeb.getSourceColumn());
                storeIf(eeb.getSourceLineText(), bodyObj, EVT_SOURCE_LINE_TEXT);
                bodyObj.put(EVT_SCRIPT, store(eeb.getScript(), false));
                break;
            default:
                throw new IllegalArgumentException("Unknown event kind: "+eventKind);
        }
        if (event.getSuccess().hasValue()) {
            obj.put(SUCCESS, event.getSuccess().getValue());
        }
        obj.put(BODY, bodyObj);
        ReferencedValue[] referencedValues = event.getReferencedValues();
        if (referencedValues != null) {
            obj.put(REFS, store(referencedValues));
        }
        PropertyBoolean running = event.isRunning();
        if (running.hasValue()) {
            obj.put(RUNNING, running.getValue());
        }
        return obj;
    }
    
    private static JSONObject newJSONObject() {
        return new LinkedJSONObject();
    }
    
    private static Object store(V8Command command, V8Arguments arguments) {
        JSONObject obj = newJSONObject();
        switch(command) {
            case Backtrace:
                Backtrace.Arguments btargs = (Backtrace.Arguments) arguments;
                storeIf(btargs.getFromFrame(), obj, FROM_FRAME);
                storeIf(btargs.getToFrame(), obj, TO_FRAME);
                storeIf(btargs.isBottom(), obj, BOTTOM);
                storeIf(btargs.isInlineRefs(), obj, INLINE_REFS);
                return obj;
            case Continue:
                Continue.Arguments cargs = (Continue.Arguments) arguments;
                obj.put(ARGS_STEP_ACTION, cargs.getStepAction().toString());
                storeIf(cargs.getStepCount(), obj, ARGS_STEP_COUNT);
                return obj;
            case Setbreakpoint:
                SetBreakpoint.Arguments sbargs = (SetBreakpoint.Arguments) arguments;
                String bpType;
                if (V8Breakpoint.Type.scriptName.equals(sbargs.getType())) {
                    bpType = "script";
                } else {
                    bpType = sbargs.getType().toString();
                }
                obj.put(TYPE, bpType);
                obj.put(TARGET, sbargs.getTarget());
                storeIf(sbargs.getLine(), obj, LINE);
                storeIf(sbargs.getColumn(), obj, COLUMN);
                storeIf(sbargs.isEnabled(), obj, BREAK_ENABLED);
                storeIf(sbargs.getCondition(), obj, BREAK_CONDITION);
                storeIf(sbargs.getIgnoreCount(), obj, BREAK_IGNORE_COUNT);
                storeIf(sbargs.getGroupId(), obj, BREAK_GROUP_ID);
                return obj;
            case Changebreakpoint:
                ChangeBreakpoint.Arguments chbargs = (ChangeBreakpoint.Arguments) arguments;
                obj.put(BREAK_POINT, chbargs.getBreakpoint());
                storeIf(chbargs.isEnabled(), obj, BREAK_ENABLED);
                obj.put(BREAK_CONDITION, chbargs.getCondition());
                storeIf(chbargs.getIgnoreCount(), obj, BREAK_IGNORE_COUNT);
                return obj;
            case Clearbreakpoint:
                ClearBreakpoint.Arguments cbargs = (ClearBreakpoint.Arguments) arguments;
                obj.put(BREAK_POINT, cbargs.getBreakpoint());
                return obj;
            case Clearbreakpointgroup:
                ClearBreakpointGroup.Arguments cbgargs = (ClearBreakpointGroup.Arguments) arguments;
                obj.put(BREAK_GROUP_ID, cbgargs.getGroupId());
                return obj;
            case Setexceptionbreak:
                SetExceptionBreak.Arguments sebargs = (SetExceptionBreak.Arguments) arguments;
                obj.put(TYPE, sebargs.getType().toString());
                obj.put(BREAK_ENABLED, sebargs.isEnabled());
                return obj;
            case Evaluate:
                Evaluate.Arguments eargs = (Evaluate.Arguments) arguments;
                obj.put(EVAL_EXPRESSION, eargs.getExpression());
                storeIf(eargs.getFrame(), obj, FRAME);
                storeIf(eargs.isGlobal(), obj, EVAL_GLOBAL);
                storeIf(eargs.isDisableBreak(), obj, EVAL_DISABLE_BREAK);
                JSONArray additionalContexts = store(eargs.getAdditionalContext());
                if (additionalContexts != null) {
                    obj.put(EVAL_ADDITIONAL_CONTEXT, additionalContexts);
                }
                return obj;
            case Frame:
                Frame.Arguments fargs = (Frame.Arguments) arguments;
                storeIf(fargs.getFrameNumber(), obj, NUMBER);
                return obj;
            case Restartframe:
                RestartFrame.Arguments ra = (RestartFrame.Arguments) arguments;
                PropertyLong frame = ra.getFrame();
                if (frame.hasValue()) {
                    obj.put(FRAME, frame.getValue());
                }
                return obj;
            case Lookup:
                Lookup.Arguments largs = (Lookup.Arguments) arguments;
                obj.put(HANDLES, array(largs.getHandles()));
                storeIf(largs.isIncludeSource(), obj, INCLUDE_SOURCE);
                return obj;
            case References:
                References.Arguments rargs = (References.Arguments) arguments;
                obj.put(TYPE, rargs.getType().name());
                obj.put(HANDLE, rargs.getHandle());
                return obj;
            case Scope:
                Scope.Arguments sargs = (Scope.Arguments) arguments;
                obj.put(NUMBER, sargs.getScopeNumber());
                storeIf(sargs.getFrameNumber(), obj, FRAME_NUMBER);
                return obj;
            case Scopes:
                Scopes.Arguments ssargs = (Scopes.Arguments) arguments;
                storeIf(ssargs.getFrameNumber(), obj, FRAME_NUMBER);
                return obj;
            case Scripts:
                Scripts.Arguments scargs = (Scripts.Arguments) arguments;
                if (scargs.getTypes() != null) {
                    obj.put(TYPES, scargs.getTypes().getIntTypes());
                }
                if (scargs.getIds() != null) {
                    obj.put(IDs, array(scargs.getIds()));
                }
                storeIf(scargs.isIncludeSource(), obj, INCLUDE_SOURCE);
                storeIf(scargs.getNameFilter(), obj, FILTER);
                storeIf(scargs.getIdFilter(), obj, FILTER);
                return obj;
            case Source:
                Source.Arguments srcargs = (Source.Arguments) arguments;
                storeIf(srcargs.getFrame(), obj, FRAME);
                storeIf(srcargs.getFromLine(), obj, FROM_LINE);
                storeIf(srcargs.getToLine(), obj, TO_LINE);
                return obj;
            case SetVariableValue:
                SetVariableValue.Arguments svargs = (SetVariableValue.Arguments) arguments;
                obj.put(NAME, svargs.getName());
                obj.put(NEW_VALUE, store(svargs.getNewValue()));
                JSONObject scope = newJSONObject();
                scope.put(NUMBER, svargs.getScopeNumber());
                storeIf(svargs.getScopeFrameNumber(), scope, FRAME_NUMBER);
                obj.put(SCOPE, scope);
                return obj;
            case Changelive:
                ChangeLive.Arguments chlargs = (ChangeLive.Arguments) arguments;
                obj.put(SCRIPT_ID, chlargs.getScriptId());
                storeIf(chlargs.isPreviewOnly(), obj, PREVIEW_ONLY);
                obj.put(NEW_SOURCE, chlargs.getNewSource());
                return obj;
            case Gc:
                GC.Arguments gcargs = (GC.Arguments) arguments;
                obj.put(TYPE, gcargs.getType());
                return obj;
            case V8flags:
                V8Flags.Arguments v8flargs = (V8Flags.Arguments) arguments;
                obj.put(FLAGS, v8flargs.getFlags());
                return obj;
            case Flags:
                Flags.Arguments flargs = (Flags.Arguments) arguments;
                Map<String, Boolean> flags = flargs.getFlags();
                if (flags != null) {
                    JSONArray arr = new JSONArray();
                    for (Map.Entry<String, Boolean> flagEntry : flags.entrySet()) {
                        JSONObject f = newJSONObject();
                        f.put(NAME, flagEntry.getKey());
                        f.put(VALUE, flagEntry.getValue());
                        arr.add(f);
                    }
                    obj.put(FLAGS, arr);
                }
                return obj;
            default:
                return null;
        }
    }
    
    private static JSONAware store(V8Command command, V8Body body) {
        switch (command) {
            case Listbreakpoints:
                JSONObject obj = newJSONObject();
                ListBreakpoints.ResponseBody lbrb = (ListBreakpoints.ResponseBody) body;
                obj.put(BREAK_POINTS, store(lbrb.getBreakpoints()));
                obj.put(BREAK_ON_EXCEPTIONS, lbrb.isBreakOnExceptions());
                obj.put(BREAK_ON_UNCAUGHT_EXCEPTIONS, lbrb.isBreakOnUncaughtExceptions());
                return obj;
            case Setbreakpoint:
                obj = newJSONObject();
                SetBreakpoint.ResponseBody sbrb = (SetBreakpoint.ResponseBody) body;
                obj.put(TYPE, sbrb.getType().toString());
                obj.put(BREAK_POINT, sbrb.getBreakpoint());
                if (V8Breakpoint.Type.scriptId.equals(sbrb.getType())) {
                    storeIf(sbrb.getScriptName(), obj, SCRIPT_ID);
                } else {
                    storeIf(sbrb.getScriptName(), obj, SCRIPT_NAME);
                }
                obj.put(LINE, getLongOrNull(sbrb.getLine()));
                obj.put(COLUMN, getLongOrNull(sbrb.getColumn()));
                obj.put(BREAK_ACTUAL_LOCATIONS, store(sbrb.getActualLocations()));
                return obj;
            case Setexceptionbreak:
                obj = newJSONObject();
                SetExceptionBreak.ResponseBody sebrb = (SetExceptionBreak.ResponseBody) body;
                obj.put(TYPE, sebrb.getType().toString());
                obj.put(BREAK_ENABLED, sebrb.isEnabled());
                return obj;
            case Clearbreakpoint:
                obj = newJSONObject();
                ClearBreakpoint.ResponseBody cbrb = (ClearBreakpoint.ResponseBody) body;
                obj.put(BREAK_POINT, cbrb.getBreakpoint());
                return obj;
            case Clearbreakpointgroup:
                obj = newJSONObject();
                ClearBreakpointGroup.ResponseBody cbgrb = (ClearBreakpointGroup.ResponseBody) body;
                obj.put(BREAK_POINTS, array(cbgrb.getBreakpointsCleared()));
                return obj;
            case Backtrace:
                obj = newJSONObject();
                Backtrace.ResponseBody brb = (Backtrace.ResponseBody) body;
                obj.put(FROM_FRAME, brb.getFromFrame());
                obj.put(TO_FRAME, brb.getToFrame());
                obj.put(TOTAL_FRAMES, brb.getTotalFrames());
                if (brb.getFrames() != null) {
                    obj.put(FRAMES, store(brb.getFrames()));
                }
                return obj;
            case Frame:
                Frame.ResponseBody frb = (Frame.ResponseBody) body;
                obj = store(frb.getFrame());
                return obj;
            case Restartframe:
                obj = newJSONObject();
                RestartFrame.ResponseBody rfrb = (RestartFrame.ResponseBody) body;
                obj.put(RESULT, store(rfrb.getResult()));
                return obj;
            case Changelive:
                obj = newJSONObject();
                ChangeLive.ResponseBody clrb = (ChangeLive.ResponseBody) body;
                obj.put(CHANGE_LOG, store(clrb.getChangeLog()));
                obj.put(RESULT, store(clrb.getResult()));
                storeIf(clrb.getStepInRecommended(), obj, STEP_IN_RECOMMENDED);
                return obj;
            case Lookup:
                Lookup.ResponseBody lrb = (Lookup.ResponseBody) body;
                obj = storeValues(lrb.getValuesByHandle());
                return obj;
            case Evaluate:
                Evaluate.ResponseBody erb = (Evaluate.ResponseBody) body;
                obj = store(erb.getValue());
                return obj;
            case References:
                References.ResponseBody rrb = (References.ResponseBody) body;
                JSONArray arrayRefs = new JSONArray();
                for (V8Value vr : rrb.getReferences()) {
                    arrayRefs.add(store(vr));
                }
                return arrayRefs;
            case Scripts:
                Scripts.ResponseBody scrrb = (Scripts.ResponseBody) body;
                return store(scrrb.getScripts());
            case SetVariableValue:
                obj = newJSONObject();
                SetVariableValue.ResponseBody svvrb = (SetVariableValue.ResponseBody) body;
                obj.put(NEW_VALUE, store(svvrb.getNewValue()));
                return obj;
            case Scope:
                Scope.ResponseBody srb = (Scope.ResponseBody) body;
                obj = store(srb.getScope());
                return obj;
            case Scopes:
                obj = newJSONObject();
                Scopes.ResponseBody ssrb = (Scopes.ResponseBody) body;
                obj.put(FROM_SCOPE, ssrb.getFromScope());
                obj.put(TO_SCOPE, ssrb.getToScope());
                obj.put(TOTAL_SCOPES, ssrb.getTotalScopes());
                obj.put(SCOPES, store(ssrb.getScopes()));
                return obj;
            case Source:
                obj = newJSONObject();
                Source.ResponseBody srcrb = (Source.ResponseBody) body;
                storeIf(srcrb.getSource(), obj, SOURCE);
                obj.put(FROM_LINE, srcrb.getFromLine());
                obj.put(TO_LINE, srcrb.getToLine());
                obj.put(FROM_POSITION, srcrb.getFromPosition());
                obj.put(TO_POSITION, srcrb.getToPosition());
                obj.put(TOTAL_LINES, srcrb.getTotalLines());
                return obj;
            case Threads:
                obj = newJSONObject();
                Threads.ResponseBody trb = (Threads.ResponseBody) body;
                obj.put(TOTAL_THREADS, trb.getNumThreads());
                obj.put(THREADS, storeThreads(trb.getIds()));
                return obj;
            case Gc:
                obj = newJSONObject();
                GC.ResponseBody gcrb = (GC.ResponseBody) body;
                obj.put(GC_BEFORE, gcrb.getBefore());
                obj.put(GC_AFTER, gcrb.getAfter());
                return obj;
            case Version:
                obj = newJSONObject();
                Version.ResponseBody vrb = (Version.ResponseBody) body;
                obj.put(BODY_VERSION, vrb.getVersion());
                return obj;
            case Flags:
                obj = newJSONObject();
                Flags.ResponseBody flrb = (Flags.ResponseBody) body;
                obj.put(FLAGS, storeFlags(flrb.getFlags()));
                return obj;
        }
        return null;
    }
    
    private static Object getLongOrNull(PropertyLong pl) {
        if (pl.hasValue()) {
            return pl.getValue();
        } else {
            return null;
        }
    }
    
    private static JSONArray store(ReferencedValue[] rvs) {
        JSONArray array = new JSONArray();
        for (ReferencedValue rv : rvs) {
            array.add(store(rv, false, false));
        }
        return array;
    }
    
    private static JSONObject store(ReferencedValue rv, boolean storeRefNotHandle, boolean noTextAndLength) {
        JSONObject obj = newJSONObject();
        //obj.put(REF, rv.getReference());
        if (rv.hasValue()) {
            if (storeRefNotHandle) {
                obj.put(REF, rv.getReference());
                store(rv.getValue(), obj, false, noTextAndLength);
            } else {
                store(rv.getValue(), obj, true, noTextAndLength);
            }
        } else {
            obj.put(REF, rv.getReference());
        }
        return obj;
    }
    
    private static JSONArray store(V8Script[] scripts) {
        JSONArray array = new JSONArray();
        for (V8Script scr : scripts) {
            array.add(store(scr));
        }
        return array;
    }
    
    private static JSONObject store(V8Script script) {
        return store(script, true);
    }
    
    private static JSONObject store(V8Script script, boolean storeHandle) {
        JSONObject obj = newJSONObject();
        storeTo(script, obj, storeHandle);
        return obj;
    }
    
    private static void storeTo(V8Script script, JSONObject obj, boolean storeHandle) {
        if (storeHandle) {
            obj.put(HANDLE, script.getHandle());
            obj.put(TYPE, script.getType().toString());
        }
        if (storeHandle) {
            if (script.getName() != null) {
                obj.put(NAME, script.getName());
            }
            obj.put(ID, script.getId());
        } else { // Just different order for easy comparison with V8 debug protocol.
            obj.put(ID, script.getId());
            if (script.getName() != null) {
                obj.put(NAME, script.getName());
            }
        }
        obj.put(SCRIPT_LINE_OFFSET, script.getLineOffset());
        obj.put(SCRIPT_COLUMN_OFFSET, script.getColumnOffset());
        obj.put(SCRIPT_LINE_COUNT, script.getLineCount());
        if (script.getData() != null) {
            obj.put(DATA, script.getData());
        }
        storeIf(script.getSource(), obj, SOURCE);
        storeIf(script.getSourceStart(), obj, SOURCE_START);
        storeIf(script.getSourceLength(), obj, SOURCE_LENGTH);
        V8Script.Type scriptType = script.getScriptType();
        if (scriptType != null) {
            obj.put(SCRIPT_TYPE, scriptType.ordinal());
        }
        V8Script.CompilationType compilationType = script.getCompilationType();
        if (compilationType != null) {
            obj.put(COMPILATION_TYPE, compilationType.ordinal());
        }
        storeIf(script.getContext(), obj, CONTEXT);
        if (script.getText() != null) {
            obj.put(TEXT, script.getText());
        }
        storeIf(script.getEvalFromScript(), obj, EVAL_FROM_SCRIPT);
        if (V8Script.CompilationType.EVAL.equals(compilationType) && script.getEvalFromLocation() != null) {
            obj.put(LINE, script.getEvalFromLocation().getLine());
            obj.put(COLUMN, script.getEvalFromLocation().getColumn());
        }
    }
    
    private static JSONObject store(V8ScriptLocation scriptLocation) {
        JSONObject obj = newJSONObject();
        obj.put(ID, scriptLocation.getId());
        obj.put(NAME, scriptLocation.getName());
        obj.put(SCRIPT_LINE_OFFSET, scriptLocation.getLine());
        obj.put(SCRIPT_COLUMN_OFFSET, scriptLocation.getColumn());
        obj.put(SCRIPT_LINE_COUNT, scriptLocation.getLineCount());
        return obj;
    }
    
    private static JSONArray store(V8Breakpoint[] breakpoints) {
        JSONArray array = new JSONArray();
        for (V8Breakpoint bp : breakpoints) {
            array.add(store(bp));
        }
        return array;
    }
    
    private static JSONObject store(V8Breakpoint bp) {
        JSONObject obj = newJSONObject();
        obj.put(NUMBER, bp.getNumber());
        storeIf(bp.getLine(), obj, LINE);
        //storeIf(bp.getColumn(), obj, COLUMN);
        obj.put(COLUMN, getLongOrNull(bp.getColumn()));
        PropertyLong groupId = bp.getGroupId();
        obj.put(BREAK_GROUP_ID, getLongOrNull(groupId));
        if (bp.getHitCount() != 0) {
            obj.put(BREAK_HIT_COUNT, bp.getHitCount());
        }
        obj.put(BREAK_ACTIVE, bp.isActive());
        obj.put(BREAK_CONDITION, bp.getCondition());
        if (bp.getIgnoreCount() != 0) {
            obj.put(BREAK_IGNORE_COUNT, bp.getIgnoreCount());
        }
        obj.put(BREAK_ACTUAL_LOCATIONS, store(bp.getActualLocations()));
        obj.put(TYPE, bp.getType().toString());
        storeIf(bp.getScriptId(), obj, SCRIPT_ID);
        storeIf(bp.getScriptName(), obj, SCRIPT_NAME);
        return obj;
    }
    
    private static JSONArray store(V8Breakpoint.ActualLocation[] actualLocations) {
        JSONArray array = new JSONArray();
        if (actualLocations != null) {
            for (V8Breakpoint.ActualLocation al : actualLocations) {
                JSONObject obj = newJSONObject();
                obj.put(LINE, al.getLine());
                obj.put(COLUMN, al.getColumn());
                storeIf(al.getScriptId(), obj, SCRIPT_ID);
                storeIf(al.getScriptName(), obj, SCRIPT_NAME);
                array.add(obj);
            }
        }
        return array;
    }
    
    private static JSONArray store(V8Frame[] frames) {
        JSONArray array = new JSONArray();
        for (V8Frame frame : frames) {
            array.add(store(frame));
        }
        return array;
    }
    
    private static JSONObject store(V8Frame frame) {
        JSONObject obj = newJSONObject();
        obj.put(TYPE, V8Value.Type.Frame.toString());
        PropertyLong index = frame.getIndex();
        obj.put(INDEX, getLongOrNull(index));
        obj.put(FRAME_RECEIVER, store(frame.getReceiver(), true, false));
        obj.put(FRAME_FUNC, store(frame.getFunction(), true, false));
        storeReference(frame.getScriptRef(), obj, SCRIPT);
        obj.put(FRAME_CONSTRUCT_CALL, frame.isConstructCall());
        obj.put(FRAME_AT_RETURN, frame.isAtReturn());
        obj.put(FRAME_DEBUGGER, frame.isDebuggerFrame());
        storeReferences(frame.getArgumentRefs(), obj, FRAME_ARGUMENTS, true);
        storeReferences(frame.getLocalRefs(), obj, FRAME_LOCALS, true);
        obj.put(POSITION, frame.getPosition());
        obj.put(LINE, frame.getLine());
        obj.put(COLUMN, frame.getColumn());
        obj.put(EVT_SOURCE_LINE_TEXT, frame.getSourceLineText());
        obj.put(SCOPES, store(frame.getScopes()));
        obj.put(TEXT, frame.getText());
        return obj;
    }
    
    private static JSONArray store(ChangeLive.ChangeLog changeLog) {
        JSONArray array = new JSONArray();
        if (changeLog != null) {
            ChangeLive.ChangeLog.BreakpointUpdate[] breakpointsUpdate = changeLog.getBreakpointsUpdate();
            if (breakpointsUpdate != null) {
                JSONObject obj = newJSONObject();
                obj.put(BREAK_POINTS_UPDATE, store(breakpointsUpdate));
                array.add(obj);
            }
            String[] droppedFrames = changeLog.getDroppedFrames();
            if (droppedFrames != null) {
                JSONObject obj = newJSONObject();
                obj.put(DROPPED_FROM_STACK, storeStringValues(droppedFrames, NAME));
                array.add(obj);
            }
            String[] namesLinkedToOldScript = changeLog.getNamesLinkedToOldScript();
            if (namesLinkedToOldScript != null) {
                JSONObject obj = newJSONObject();
                obj.put(LINKED_TO_OLD_SCRIPT, storeStringValues(namesLinkedToOldScript, NAME));
                array.add(obj);
            }
            ChangeLive.ChangeLog.FunctionPatched functionPatched = changeLog.getFunctionPatched();
            if (functionPatched != null) {
                JSONObject obj = newJSONObject();
                obj.put(FUNCTION_PATCHED, functionPatched.getFunction());
                storeIf(functionPatched.getFunctionInfoNotFound(), obj, FUNCTION_INFO_NOT_FOUND);
                array.add(obj);
            }
            ChangeLive.ChangeLog.PositionPatched[] patchedPositions = changeLog.getPatchedPositions();
            if (patchedPositions != null) {
                JSONObject obj = newJSONObject();
                obj.put(POSITION_PATCHED, store(patchedPositions));
                array.add(obj);
            }
        }
        return array;
    }
    
    private static JSONArray store(ChangeLive.ChangeLog.BreakpointUpdate[] breakpointsUpdate) {
        JSONArray array = new JSONArray();
        for (ChangeLive.ChangeLog.BreakpointUpdate bpu : breakpointsUpdate) {
            JSONObject obj = newJSONObject();
            obj.put(ID, bpu.getId());
            storeIf(bpu.getNewId(), obj, NEW_ID);
            storeIf(bpu.getNewPositions(), obj, NEW_POSITIONS);
            storeIf(bpu.getOldPositions(), obj, POSITIONS);
            obj.put(TYPE, bpu.getType().toString());
            array.add(obj);
        }
        return array;
    }
    
    private static JSONArray store(ChangeLive.ChangeLog.PositionPatched[] patchedPositions) {
        JSONArray array = new JSONArray();
        for (ChangeLive.ChangeLog.PositionPatched pp : patchedPositions) {
            JSONObject obj = newJSONObject();
            storeIf(pp.getName(), obj, NAME);
            storeIf(pp.getInfoNotFound(), obj, INFO_NOT_FOUND);
            array.add(obj);
        }
        return array;
    }
    
    private static JSONObject store(ChangeLive.Result result) {
        JSONObject obj = newJSONObject();
        obj.put(CHANGE_TREE, store(result.getChangeTree()));
        obj.put(TEXTUAL_DIFF, store(result.getDiff()));
        obj.put(UPDATED, result.isUpdated());
        storeIf(result.getStackModified(), obj, STACK_MODIFIED);
        storeIf(result.getStackUpdateNeedsStepIn(), obj, STACK_UPDATE_NEEDS_STEP_IN);
        storeIf(result.getCreatedScriptName(), obj, CREATED_SCRIPT_NAME);
        return obj;
    }
    
    private static JSONObject store(ChangeLive.Result.ChangeTree changeTree) {
        JSONObject obj = newJSONObject();
        obj.put(NAME, changeTree.getName());
        storeIf(changeTree.getPositions(), obj, POSITIONS);
        if (changeTree.getStatus() != null) {
            obj.put(STATUS, changeTree.getStatus().toString());
        }
        obj.put(CHILDREN, store(changeTree.getChildren()));
        if (changeTree.getNewChildren() != null) {
            obj.put(NEW_CHILDREN, store(changeTree.getNewChildren()));
        }
        storeIf(changeTree.getStatusExplanation(), obj, STATUS_EXPLANATION);
        storeIf(changeTree.getNewPositions(), obj, NEW_POSITIONS);
        return obj;
    }
    
    private static JSONObject store(ChangeLive.Result.TextualDiff diff) {
        JSONObject obj = newJSONObject();
        obj.put(OLD_LEN, diff.getOldLength());
        obj.put(NEW_LEN, diff.getNewLength());
        obj.put(CHUNKS, array(diff.getChunks()));
        return obj;
    }
    
    private static void storeIf(ChangeLive.ChangeLog.BreakpointUpdate.Position position, JSONObject obj, String propName) {
        if (position != null) {
            JSONObject pos = newJSONObject();
            pos.put(POSITION, position.getPosition());
            pos.put(LINE, position.getLine());
            pos.put(COLUMN, position.getColumn());
            obj.put(propName, pos);
        }
    }
    
    private static JSONArray store(ChangeLive.Result.ChangeTree[] children) {
        JSONArray array = new JSONArray();
        if (children != null) {
            for (ChangeLive.Result.ChangeTree ct : children) {
                array.add(store(ct));
            }
        }
        return array;
    }
    
    private static void storeIf(ChangeLive.Result.ChangeTree.Positions positions, JSONObject obj, String propName) {
        if (positions != null) {
            JSONObject pos = newJSONObject();
            pos.put(START_POSITION, positions.getStartPosition());
            pos.put(END_POSITION, positions.getEndPosition());
            obj.put(propName, pos);
        }
    }
    
    private static JSONObject storeValues(Map<Long, V8Value> values) {
        JSONObject obj = newJSONObject();
        for (V8Value vv : values.values()) {
            obj.put(Long.toString(vv.getHandle()), store(vv));
        }
        return obj;
    }
    
    private static JSONArray store(V8Scope[] scopes) {
        JSONArray array = new JSONArray();
        for (V8Scope scope : scopes) {
            array.add(store(scope));
        }
        return array;
    }
    
    private static JSONObject store(V8Scope scope) {
        JSONObject obj = newJSONObject();
        obj.put(TYPE, scope.getType().ordinal());
        obj.put(SCOPE_INDEX, scope.getIndex());
        storeIf(scope.getFrameIndex(), obj, FRAME_INDEX);
        if (scope.getObject() != null) {
            obj.put(OBJECT, store(scope.getObject(), false, true));
        }
        storeIf(scope.getText(), obj, TEXT);
        return obj;
    }
    
    private static JSONArray storeThreads(Map<Long, Boolean> threads) {
        JSONArray array = new JSONArray();
        for (Map.Entry<Long, Boolean> thread : threads.entrySet()) {
            JSONObject obj = newJSONObject();
            obj.put(CURRENT, thread.getValue());
            obj.put(ID, thread.getKey());
            array.add(obj);
        }
        return array;
    }
    
    private static JSONArray storeFlags(Map<String, Boolean> flags) {
        JSONArray array = new JSONArray();
        for (Map.Entry<String, Boolean> flag : flags.entrySet()) {
            JSONObject obj = newJSONObject();
            obj.put(NAME, flag.getKey());
            obj.put(VALUE, flag.getValue());
            array.add(obj);
        }
        return array;
    }
    
    private static JSONObject store(Map<String, Object> map) {
        JSONObject obj = newJSONObject();
        obj.putAll(map);
        return obj;
    }
    
    private static JSONArray array(long[] array) {
        JSONArray jsArray = new JSONArray();
        for (int i = 0; i < array.length; i++) {
            jsArray.add(array[i]);
        }
        return jsArray;
    }
    
    private static JSONArray storeStringValues(String[] ss, String propName) {
        JSONArray array = new JSONArray();
        for (String s : ss) {
            JSONObject obj = newJSONObject();
            obj.put(NAME, s);
            array.add(obj);
        }
        return array;
    }
    
    private static void storeIf(PropertyBoolean prop, JSONObject obj, String propertyName) {
        if (prop.hasValue()) {
            obj.put(propertyName, prop.getValue());
        }
    }
    
    private static void storeIf(PropertyLong prop, JSONObject obj, String propertyName) {
        if (prop.hasValue()) {
            obj.put(propertyName, prop.getValue());
        }
    }
    
    private static void storeIf(String prop, JSONObject obj, String propertyName) {
        if (prop != null) {
            obj.put(propertyName, prop);
        }
    }
    
    private static void storeIf(ReferencedValue rv, JSONObject obj, String propertyName) {
        if (rv == null) {
            return ;
        }
        JSONObject ref = newJSONObject();
        ref.put(REF, rv.getReference());
        if (rv.hasValue()) {
            store(rv.getValue(), ref, false, false);
        }
        obj.put(propertyName, ref);
    }
    
    private static JSONArray store(Evaluate.Arguments.Context[] contexts) {
        if (contexts == null) {
            return null;
        }
        JSONArray array = new JSONArray();
        for (Evaluate.Arguments.Context c : contexts) {
            array.add(store(c));
        }
        return array;
    }
    
    private static JSONObject store(Evaluate.Arguments.Context context) {
        JSONObject obj = newJSONObject();
        obj.put(NAME, context.getName());
        obj.put(HANDLE, context.getHandle());
        return obj;
    }
    
    private static JSONObject store(NewValue value) {
        JSONObject obj = newJSONObject();
        if (value.getHandle().hasValue()) {
            obj.put(HANDLE, value.getHandle().getValue());
        } else {
            obj.put(TYPE, value.getType().toString());
            storeIf(value.getDescription(), obj, STRING_DESCRIPTION);
        }
        return obj;
    }
    
    private static JSONObject store(V8Value value) {
        JSONObject obj = newJSONObject();
        store(value, obj, true, false);
        return obj;
    }
    
    private static void store(V8Value value, JSONObject obj, boolean storeHandle, boolean noTextAndLength) {
        if (storeHandle) {
            obj.put(HANDLE, value.getHandle());
        }
        V8Value.Type type = value.getType();
        obj.put(TYPE, type.toString());
        switch (type) {
            case Boolean:
                V8Boolean vb = (V8Boolean) value;
                obj.put(VALUE, vb.getValue());
                break;
            case Number:
                V8Number vn = (V8Number) value;
                V8Number.Kind kind = vn.getKind();
                switch (kind) {
                    case Double:
                        double dv = vn.getDoubleValue();
                        if (dv == Double.POSITIVE_INFINITY) {
                            obj.put(VALUE, INFINITY);
                        } else if (dv == Double.NEGATIVE_INFINITY) {
                            obj.put(VALUE, "-"+INFINITY);
                        } else if (Double.isNaN(dv)) {
                            obj.put(VALUE, NaN);
                        } else {
                            obj.put(VALUE, dv);
                        }
                        break;
                    case Long:
                        obj.put(VALUE, vn.getLongValue());
                        break;
                    default:
                        throw new IllegalArgumentException("Unhandled number kind: "+kind);
                }
                break;
            case String:
                V8String vs = (V8String) value;
                String vss = vs.getValue();
                obj.put(VALUE, vss);
                if (!noTextAndLength) {
                    obj.put(LENGTH, vss.length());
                }
                break;
            case Function:
                V8Function vf = (V8Function) value;
                if (vf.isResolved().hasValue()) { // Hack to be compliant with original V8 protocol
                    obj.put(VALUE_CLASS_NAME, vf.getClassName());
                }
                storeReferenceIf(vf.getConstructorFunctionHandle(), obj, VALUE_CONSTRUCTOR_FUNCTION);
                storeReferenceIf(vf.getProtoObjectHandle(), obj, VALUE_PROTO_OBJECT);
                storeReferenceIf(vf.getPrototypeObjectHandle(), obj, VALUE_PROTOTYPE_OBJECT);
                storeIf(vf.getName(), obj, NAME);
                storeIf(vf.getInferredName(), obj, FUNCTION_INFERRED_NAME);
                storeIf(vf.isResolved(), obj, FUNCTION_RESOLVED);
                storeIf(vf.getSource(), obj, SOURCE);
                storeReferenceIf(vf.getScriptRef(), obj, SCRIPT);
                storeIf(vf.getScriptId(), obj, SCRIPTID);
                storeIf(vf.getPosition(), obj, POSITION);
                storeIf(vf.getLine(), obj, LINE);
                storeIf(vf.getColumn(), obj, COLUMN);
                V8Scope[] scopes = vf.getScopes();
                if (scopes != null) {
                    obj.put(SCOPES, store(scopes));
                }
                if (vf.getProperties() != null || vf.getArray() != null && vf.getArray().getLength() > 0) {
                    obj.put(VALUE_PROPERTIES, storeProperties(vf.getProperties(), vf.getArray()));
                }
                break;
            case Generator:
                V8Generator gf = (V8Generator) value;
                obj.put(VALUE_CLASS_NAME, gf.getClassName());
                storeReferenceIf(gf.getConstructorFunctionHandle(), obj, VALUE_CONSTRUCTOR_FUNCTION);
                storeReferenceIf(gf.getProtoObjectHandle(), obj, VALUE_PROTO_OBJECT);
                storeReferenceIf(gf.getPrototypeObjectHandle(), obj, VALUE_PROTOTYPE_OBJECT);
                storeReferenceIf(gf.getFunctionHandle(), obj, FRAME_FUNC);
                storeReferenceIf(gf.getReceiverHandle(), obj, FRAME_RECEIVER);
                if (gf.getProperties() != null) {
                    obj.put(VALUE_PROPERTIES, storeProperties(gf.getProperties(), null));
                }
                break;
            case Object:
            case Error:
            case Regexp:
                V8Object vo = (V8Object) value;
                obj.put(VALUE_CLASS_NAME, vo.getClassName());
                storeReferenceIf(vo.getConstructorFunctionHandle(), obj, VALUE_CONSTRUCTOR_FUNCTION);
                storeReferenceIf(vo.getProtoObjectHandle(), obj, VALUE_PROTO_OBJECT);
                storeReferenceIf(vo.getPrototypeObjectHandle(), obj, VALUE_PROTOTYPE_OBJECT);
                if (vo.getProperties() != null || vo.getArray() != null && vo.getArray().getLength() > 0) {
                    obj.put(VALUE_PROPERTIES, storeProperties(vo.getProperties(), vo.getArray()));
                }
                break;
            case Frame:
                // ? TODO
                break;
            case Script:
                V8ScriptValue vsv = (V8ScriptValue) value;
                storeTo(vsv.getScript(), obj, true);
                break;
            case Null:
                if (noTextAndLength) {
                    obj.put(VALUE, null);
                }
                break;
        }
        if (value.getText() != null && !noTextAndLength) {
            obj.put(TEXT, value.getText());
        }
    }
    
    private static void storeReferenceIf(PropertyLong ref, JSONObject obj, String propertyName) {
        if (ref.hasValue()) {
            storeReference(ref.getValue(), obj, propertyName);
        }
    }
    
    private static void storeReference(long ref, JSONObject obj, String propertyName) {
        JSONObject refObj = newJSONObject();
        refObj.put(REF, ref);
        obj.put(propertyName, refObj);
    }
    
    private static void storeReferences(Map<String, ReferencedValue> rvals,
                                        JSONObject obj, String propertyName,
                                        boolean storeRefNotHandle) {
        if (rvals == null) {
            return ;
        }
        JSONArray array = new JSONArray();
        for (Map.Entry<String, ReferencedValue> rval : rvals.entrySet()) {
            JSONObject elm = newJSONObject();
            if (rval.getKey() != null) {
                elm.put(NAME, rval.getKey());
            }
            elm.put(VALUE, store(rval.getValue(), storeRefNotHandle, true));
            array.add(elm);
        }
        obj.put(propertyName, array);
    }
    
    private static JSONArray storeProperties(Map<String, V8Object.Property> properties, V8Object.Array array) {
        JSONArray arrObj = new JSONArray();
        if (properties != null) {
            for (String propName : properties.keySet()) {
                V8Object.Property prop = properties.get(propName);
                JSONObject propObj = newJSONObject();
                propObj.put(NAME, propName);
                if (prop.getAttributes() != 0) {
                    propObj.put(ATTRIBUTES, prop.getAttributes());
                }
                V8Object.Property.Type type = prop.getType();
                if (type != null) {
                    propObj.put(PROPERTY_TYPE, type.ordinal());
                } else {
                    propObj.put(PROPERTY_TYPE, 0);
                }
                propObj.put(REF, prop.getReference());
                arrObj.add(propObj);
            }
        }
        if (array != null) {
            V8Object.IndexIterator indexIterator = array.getIndexIterator();
            while (indexIterator.hasNextIndex()) {
                JSONObject arrElm = newJSONObject();
                long index = indexIterator.nextIndex();
                arrElm.put(NAME, index);
                arrElm.put(PROPERTY_TYPE, 0);
                arrElm.put(REF, array.getReferenceAt(index));
                arrObj.add(arrElm);
            }
        }
        return arrObj;
    }
}
