/*
 * Copyright (C) 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>

namespace Inspector {

typedef enum {
    ScriptBreakpointActionTypeLog,
    ScriptBreakpointActionTypeEvaluate,
    ScriptBreakpointActionTypeSound,
    ScriptBreakpointActionTypeProbe
} ScriptBreakpointActionType;

struct ScriptBreakpointAction {
    ScriptBreakpointAction(ScriptBreakpointActionType type, int identifier, const String& data)
        : type(type)
        , identifier(identifier)
        , data(data)
    {
    }

    ScriptBreakpointActionType type;
    int identifier;
    String data;
};

typedef Vector<ScriptBreakpointAction> BreakpointActions;

struct ScriptBreakpoint {
    ScriptBreakpoint()
    {
    }

    ScriptBreakpoint(int lineNumber, int columnNumber, const String& condition, bool autoContinue, unsigned ignoreCount)
        : lineNumber(lineNumber)
        , columnNumber(columnNumber)
        , condition(condition)
        , autoContinue(autoContinue)
        , ignoreCount(ignoreCount)
    {
    }

    ScriptBreakpoint(int lineNumber, int columnNumber, const String& condition, BreakpointActions& actions, bool autoContinue, unsigned ignoreCount)
        : lineNumber(lineNumber)
        , columnNumber(columnNumber)
        , condition(condition)
        , actions(actions)
        , autoContinue(autoContinue)
        , ignoreCount(ignoreCount)
    {
    }

    int lineNumber { 0 };
    int columnNumber { 0 };
    String condition;
    BreakpointActions actions;
    bool autoContinue { false };
    unsigned ignoreCount { 0 };
};

} // namespace Inspector
