public class InBinaryOp extends InDebuggerMessage {

    public static final int ID = 57;

    public long id;

    public List<Long> parentsIds;
    public List<Variable> variables;

    @Override
    public String toString() {
        return super.toString() + "(count:" + parentsIds.size() + ")";
    }

    public InBinaryOp(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        id = readDWord();
        parentsIds = new ArrayList<>();
        variables = new ArrayList<>();

        if (available() > 0) {
            parentsIds.add(readPtr(c));
            variables.add(readVariable(c));
        }
    }

} public class InBreakAt extends InDebuggerMessage {

    public static final int ID = 16;

    public long id;
    public int file;
    public int line;
    public String stack;

    @Override
    public String toString() {
        return super.toString() + "(id=" + id + ", file=" + file + ", line=" + line + ", stack='" + stack + "')";
    }

    public InBreakAt(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        if (!wideLines) {
            file = readWord();
            line = readWord();
        } else {
            file = (int) readDWord();
            line = (int) readDWord();
        }
        id = readPtr(c);
        stack = readString();
    }

    @Override
    public void exec() {
        connection.isPaused = true;
    }

} public class InBreakAtExt extends InDebuggerMessage {

    public static final int ID = 27;

    public int file;
    public int line;

    public List<Integer> files;
    public List<Integer> lines;
    public List<Long> ids;
    public List<String> stacks;

    @Override
    public String toString() {
        return super.toString() + "(file=" + file + ", line=" + line + ", items.count=" + files.size() + ")";
    }

    public InBreakAtExt(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        if (!wideLines) {
            file = readWord();
            line = readWord();
        } else {
            file = (int) readDWord();
            line = (int) readDWord();
        }
        long num = readDWord();
        files = new ArrayList<>();
        lines = new ArrayList<>();
        ids = new ArrayList<>();
        stacks = new ArrayList<>();
        for (long i = 0; i < num; i++) {
            int file_i;
            int line_i;
            if (!wideLines) {
                file_i = readWord();
                line_i = readWord();
            } else {
                file_i = (int) readDWord();
                line_i = (int) readDWord();
            }
            long id = readPtr(c);
            String stack = readString();
            files.add(file_i);
            lines.add(line_i);
            ids.add(id);
            stacks.add(stack);
        }
    }

} public class InCallFunction extends InDebuggerMessage {

    public static final int ID = 54;

    public List<Long> parentsIds;
    public List<Variable> variables;

    @Override
    public String toString() {
        return super.toString() + "(items.count=" + parentsIds.size() + ")";
    }

    public InCallFunction(DebuggerConnection c, byte[] data) {
        super(c, ID, data);

        parentsIds = new ArrayList<>();
        variables = new ArrayList<>();

        if (available() > 0) {
            parentsIds.add(readPtr(c));
            variables.add(readVariable(c));
        }
    }

} public class InConstantPool extends InDebuggerMessage {

    public static final int ID = 43;

    public int swfIndex;
    public List<Long> ids;
    public List<Variable> vars;

    @Override
    public String toString() {
        return super.toString() + "(swfIndex=" + swfIndex + ",vars.count=" + vars.size() + ")";
    }

    public InConstantPool(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        swfIndex = readWord();
        int count = (int) readDWord();
        ids = new ArrayList<>();
        vars = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            ids.add(readPtr(c));
            vars.add(readVariable(c));
        }
    }

} public class InContinue extends InDebuggerMessage {

    public static final int ID = 17;

    public InContinue(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
    }

    @Override
    public void exec() {
        connection.isPaused = false;
    }

} public class InErrorException extends InDebuggerMessage {

    public static final int ID = 36;

    public String exceptionMessage;
    public boolean willExceptionBeCaught;
    public long offset;
    public Variable thrownVar;

    @Override
    public String toString() {
        return super.toString() + "(msg=" + exceptionMessage + ", willBeCaught=" + willExceptionBeCaught + ", offset=" + offset + ", thrownVar=" + thrownVar + ")";
    }

    public InErrorException(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        offset = readDWord();
        willExceptionBeCaught = false;

        if (available() > 0) { //FP9+
            exceptionMessage = readString();
            if (available() > 0) {
                if (readByte() != 0) {
                    willExceptionBeCaught = (readByte() != 0 ? true
                            : false);
                    readPtr(c);
                    thrownVar = readVariable(c);
                }
            }
        } else {
            exceptionMessage = "";
        }
    }

} public class InFrame extends InDebuggerMessage {

    public static final int ID = 31;

    public int depth;
    public List<Variable> registers;

    public List<Variable> variables;
    public List<Long> frameIds;

    public List<Variable> arguments;
    public List<Long> argumentFrameIds;

    public List<Variable> scopeChain;
    public List<Long> scopeChainFrameIds;

    public long frameId = -1;
    public Variable frame;

    @Override
    public String toString() {
        return super.toString() + "(depth=" + depth + ", registers.count=" + registers.size() + ", variables.count=" + variables.size() + ")";
    }

    public InFrame(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        depth = (int) readDWord();
        registers = new ArrayList<>();

        if (depth > -1) {
            int num = (int) readDWord();
            for (int i = 0; i < num; i++) {
                registers.add(readRegister(c, i + 1));
            }
        }

        int currentArg = -1;
        boolean gettingScopeChain = false;
        if (available() > 0) {
            frameId = readPtr(c);
            frame = readVariable(c);
        }
        variables = new ArrayList<>();
        frameIds = new ArrayList<>();
        arguments = new ArrayList<>();
        argumentFrameIds = new ArrayList<>();
        scopeChain = new ArrayList<>();
        scopeChainFrameIds = new ArrayList<>();
        while (available() > 0) {
            long frameId = readPtr(c);
            Variable child = readVariable(c);
            if (currentArg == -1 && child.name.equals(ARGUMENTS_MARKER)) {
                currentArg = 0;
                gettingScopeChain = false;
                continue;
            } else if (child.name.equals(SCOPE_CHAIN_MARKER)) {
                currentArg = -1;
                gettingScopeChain = true;
                continue;
            } else if (currentArg >= 0) {
                currentArg++;
                if (child.name.equals("undefined")) {
                    child.name = "_arg" + currentArg;
                }
            }

            if (gettingScopeChain) {
                scopeChain.add(child);
                scopeChainFrameIds.add(frameId);
            } else if (currentArg >= 0) {
                arguments.add(child);
                argumentFrameIds.add(frameId);
            } else {
                variables.add(child);
                frameIds.add(frameId);
            }
        }
    }

} public class InGetActions extends InDebuggerMessage {

    public static final int ID = 41;

    public int swfIndex;
    public long offset;
    public byte[] actionData;

    @Override
    public String toString() {
        return super.toString() + "(swfIndex=" + swfIndex + ", offset=" + offset + ", actionData.length=" + actionData.length + ")";
    }

    public InGetActions(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        swfIndex = readWord();
        readWord(); //0 - reserved
        offset = readDWord();
        long len = readDWord();
        actionData = readBytes((int) len);
    }

} public class InGetVariable extends InDebuggerMessage {

    public static final int ID = 30;

    public List<Variable> childs;
    public List<Long> childsIds;

    public Variable parent;
    public long parentId;

    @Override
    public String toString() {
        return super.toString() + "(parentId=" + parentId + ", parent=" + parent + ", childs.length=" + childs.size() + ")";
    }

    public InGetVariable(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        childs = new ArrayList<>();
        childsIds = new ArrayList<>();
        boolean hasParent = false;

        while (available() > 0) {
            long id = readPtr(c);
            if (!hasParent) {
                parentId = id;
                parent = readVariable(c);
                hasParent = true;
            } else {
                Variable child = readVariable(c);
                /*if (showMember(child)) {

                 } else {
                 if (isTraits(child)) {
                 //if name is MyClass$something, then it belongs to MyClass - static
                 }
                 }*/
                childs.add(child);
                childsIds.add(id);
            }
        }
    }

} public class InOption extends InDebuggerMessage {

    public static final int ID = 32;

    public String s;
    public String v;

    public static String OPTION_MOVIE = "movie";
    public static String OPTION_PASSWORD = "password";
    public static String OPTION_CONCURRENT_PLAYER = "concurrent_player";
    public static String OPTION_WIDE_LINE_PLAYER = "wide_line_player";
    public static String OPTION_CAN_TERMINATE = "can_terminate";
    public static String OPTION_CAN_BREAK_ON_ALL_EXCEPTIONS = "can_break_on_all_exceptions";
    public static String OPTION_CAN_SET_WATCHPOINTS = "can_set_watchpoints";
    public static String OPTION_CAN_CALL_FUNCTIONS = "can_call_functions";
    public static String OPTION_TRACE = "trace";

    @Override
    public String toString() {
        return super.toString() + "(name=" + s + ", value=" + v + ")";
    }

    public InOption(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        s = readString();
        v = readString();
    }

    @Override
    public void exec() {
        connection.options.put(s, v);
    }

} public class InRemoveBreakpoint extends InDebuggerMessage {

    public static final int ID = 22;

    public List<Integer> breakPointFiles;
    public List<Integer> breakPointLines;

    @Override
    public String toString() {
        return super.toString() + "(breakPoints.count=" + breakPointFiles.size() + ")";
    }

    public InRemoveBreakpoint(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        breakPointFiles = new ArrayList<>();
        breakPointLines = new ArrayList<>();
        long count = readDWord();
        for (int i = 0; i < count; i++) {
            if (c.wideLines) {
                breakPointFiles.add((int) readDWord());
                breakPointLines.add((int) readDWord());
            } else {
                breakPointFiles.add((int) readWord());
                breakPointLines.add((int) readWord());
            }
        }
    }

} public class InSetBreakpoint extends InDebuggerMessage {

    public static final int ID = 19;

    public List<Integer> files;
    public List<Integer> lines;

    @Override
    public String toString() {
        return super.toString() + "(bp.count=" + files.size() + ")";
    }

    public InSetBreakpoint(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        int count = (int) readDWord();
        files = new ArrayList<>();
        lines = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            if (!wideLines) {
                files.add(readWord());
                lines.add(readWord());
            } else {
                files.add((int) readDWord());
                lines.add((int) readDWord());
            }
        }
    }

} public class InSetProperty extends InDebuggerMessage {

    public static final int ID = 1;

    public long objId;
    public int item;
    public String value;

    public static final String[] PROPERTY_NAMES = new String[]{
        "_x", "_y", "_xscale", "_yscale", "_currentframe", "_totalframes", "_alpha", "_visible",
        "_width", "_height", "_rotation", "_target", "_framesloaded", "_name", "_droptarget",
        "_url", "_highquality", "_focusrect", "_soundbuftime", "_quality", "_xmouse", "_ymouse"
    };

    @Override
    public String toString() {
        return super.toString() + "(objId=" + objId + ", item=" + item + ", value=" + value + ")";
    }

    public InSetProperty(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        objId = readPtr(c);
        item = readWord();
        value = readString();
    }

} public class InSwfInfo extends InDebuggerMessage {

    public static final int ID = 42;

    public List<SwfInfo> swfInfos;

    public static class SwfInfo {

        public long index;
        public long id;
        public boolean debugComing;
        public int vmVersion;
        public int rsvd1;
        public long swfSize;
        public long swdSize;
        public long scriptCount;
        public long offsetCount;
        public long breakpointCount;
        public long port;
        public String path;
        public String url;
        public String host;

        public Map<Long, Integer> local2global = new HashMap<>();

        @Override
        public String toString() {
            return "SwfInfo(index=" + index + ", id=" + id + ", vmVersion=" + vmVersion + ", swfSize=" + swfSize + ", swdSize=" + swdSize + ", scriptCount=" + scriptCount + ", path=" + path + ", url=" + url + ", host=" + host + ")";
        }

    }

    @Override
    public String toString() {
        return super.toString() + "(swfInfo.count=" + swfInfos.size() + ")";
    }

    public InSwfInfo(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        int count = readWord();
        swfInfos = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            SwfInfo s = new SwfInfo();
            s.index = readDWord();

            s.id = readPtr(c);
            if (s.id != 0) {
                s.debugComing = readByte() == 0 ? false : true;
                s.vmVersion = readByte();
                s.rsvd1 = readWord();
                s.swfSize = readDWord();
                s.swdSize = readDWord();
                s.scriptCount = readDWord();
                s.offsetCount = readDWord();
                s.breakpointCount = readDWord();

                s.port = readDWord();
                s.path = readString();
                s.url = readString();
                s.host = readString();

                s.local2global = new HashMap<>();
                if (s.swdSize > 0) {
                    long num = readDWord();
                    for (int j = 0; j < num; j++) {
                        if (available() < c.sizeOfPtr) {
                            break;
                        }
                        long local = readPtr(c);
                        int global = (int) readDWord();
                        s.local2global.put(local, global);
                    }
                }
            }
            swfInfos.add(s);
        }
    }

} public class InWatch2 extends InDebuggerMessage {

    public static final int ID = 55;

    public int success;
    public int oldFlags;
    public int oldTag;
    public int flags;
    public long objId;
    public String name;

    @Override
    public String toString() {
        return super.toString() + "(success=" + success + ", oldFlags=" + oldFlags + ", oldTag=" + oldTag + ", flags=" + flags + ", objId=" + objId + ", name=" + name + ")";
    }

    public InWatch2(DebuggerConnection c, byte[] data) {
        super(c, ID, data);
        success = readWord();
        oldFlags = readWord();
        oldTag = readWord();
        flags = readWord();
        objId = readWord();
        if (c.isAS3) {
            objId = readDWord();
        }
        name = readString();
    }

}
import com.jpexs.debugger.flash.messages.in.InAskBreakpoints;
import com.jpexs.debugger.flash.messages.in.InBinaryOp;
import com.jpexs.debugger.flash.messages.in.InBreakAt;
import com.jpexs.debugger.flash.messages.in.InBreakAtExt;
import com.jpexs.debugger.flash.messages.in.InBreakReason;
import com.jpexs.debugger.flash.messages.in.InCallFunction;
import com.jpexs.debugger.flash.messages.in.InConstantPool;
import com.jpexs.debugger.flash.messages.in.InContinue;
import com.jpexs.debugger.flash.messages.in.InDeleteVariable;
import com.jpexs.debugger.flash.messages.in.InErrorConsole;
import com.jpexs.debugger.flash.messages.in.InErrorException;
import com.jpexs.debugger.flash.messages.in.InErrorExecLimit;
import com.jpexs.debugger.flash.messages.in.InErrorProtoLimit;
import com.jpexs.debugger.flash.messages.in.InErrorScriptStuck;
import com.jpexs.debugger.flash.messages.in.InErrorStackUnderflow;
import com.jpexs.debugger.flash.messages.in.InErrorTarget;
import com.jpexs.debugger.flash.messages.in.InErrorURLOpen;
import com.jpexs.debugger.flash.messages.in.InErrorWith;
import com.jpexs.debugger.flash.messages.in.InErrorZeroDivide;
import com.jpexs.debugger.flash.messages.in.InExit;
import com.jpexs.debugger.flash.messages.in.InFrame;
import com.jpexs.debugger.flash.messages.in.InGetActions;
import com.jpexs.debugger.flash.messages.in.InGetFncNames;
import com.jpexs.debugger.flash.messages.in.InGetSwd;
import com.jpexs.debugger.flash.messages.in.InGetSwf;
import com.jpexs.debugger.flash.messages.in.InGetVariable;
import com.jpexs.debugger.flash.messages.in.InIsolate;
import com.jpexs.debugger.flash.messages.in.InIsolateCreate;
import com.jpexs.debugger.flash.messages.in.InIsolateEnumerate;
import com.jpexs.debugger.flash.messages.in.InIsolateExit;
import com.jpexs.debugger.flash.messages.in.InNewObject;
import com.jpexs.debugger.flash.messages.in.InNotSynced;
import com.jpexs.debugger.flash.messages.in.InNumScript;
import com.jpexs.debugger.flash.messages.in.InOption;
import com.jpexs.debugger.flash.messages.in.InParam;
import com.jpexs.debugger.flash.messages.in.InPassAllExceptionsToDebugger;
import com.jpexs.debugger.flash.messages.in.InPlaceObject;
import com.jpexs.debugger.flash.messages.in.InProcessTag;
import com.jpexs.debugger.flash.messages.in.InRemoveBreakpoint;
import com.jpexs.debugger.flash.messages.in.InRemoveExceptionBreakpoint;
import com.jpexs.debugger.flash.messages.in.InRemoveObject;
import com.jpexs.debugger.flash.messages.in.InRemoveScript;
import com.jpexs.debugger.flash.messages.in.InScript;
import com.jpexs.debugger.flash.messages.in.InSetActiveIsolate;
import com.jpexs.debugger.flash.messages.in.InSetBreakpoint;
import com.jpexs.debugger.flash.messages.in.InSetExceptionBreakpoint;
import com.jpexs.debugger.flash.messages.in.InSetLocalVariables;
import com.jpexs.debugger.flash.messages.in.InSetMenuState;
import com.jpexs.debugger.flash.messages.in.InSetProperty;
import com.jpexs.debugger.flash.messages.in.InSetVariable;
import com.jpexs.debugger.flash.messages.in.InSetVariable2;
import com.jpexs.debugger.flash.messages.in.InSquelch;
import com.jpexs.debugger.flash.messages.in.InSwfInfo;
import com.jpexs.debugger.flash.messages.in.InTrace;
import com.jpexs.debugger.flash.messages.in.InUnknown;
import com.jpexs.debugger.flash.messages.in.InVersion;
import com.jpexs.debugger.flash.messages.in.InWatch;
import com.jpexs.debugger.flash.messages.in.InWatch2;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
 *  Copyright (C) 2015 JPEXS, All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 */
package com.jpexs.debugger.flash;


/**
 *
 * @author JPEXS
 */
public class InDebuggerMessage extends DebuggerMessage {

    /**
     * Enums originally extracted from shared_tcserver/tcparser.h; these
     * correspond to Flash player values that are currently in playerdebugger.h,
     * class DebugAtomType.
     */
    public int type;
    public byte[] data;

    public static final int DEFAULT_ISOLATE_ID = 1;

    protected int targetIsolate;

    private ByteArrayInputStream is;

    protected boolean wideLines = false;

    protected DebuggerConnection connection;

    protected InDebuggerMessage(DebuggerConnection c, int type, byte[] data) {
        this.data = data;
        is = new ByteArrayInputStream(data);
        connection = c;
        targetIsolate = c.activeIsolateId;
        wideLines = c.wideLines;
    }

    public static final InDebuggerMessage getInstance(DebuggerConnection c, int type, byte[] data) {
        switch (type) {
            case InUnknown.ID:
                return new InUnknown(c, data);
            case InSetMenuState.ID:
                return new InSetMenuState(c, data);
            case InSetProperty.ID: