/*
 * Copyright (c) 2010, 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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.
 */

#ifndef V8_INSPECTOR_V8INSPECTORIMPL_H_
#define V8_INSPECTOR_V8INSPECTORIMPL_H_

#include <functional>
#include <map>

#include "src/base/macros.h"
#include "src/inspector/protocol/Protocol.h"

#include "include/v8-inspector.h"

namespace v8_inspector {

class InspectedContext;
class V8Console;
class V8ConsoleMessageStorage;
class V8Debugger;
class V8DebuggerAgentImpl;
class V8InspectorSessionImpl;
class V8ProfilerAgentImpl;
class V8RuntimeAgentImpl;
class V8StackTraceImpl;

class V8InspectorImpl : public V8Inspector {
 public:
  V8InspectorImpl(v8::Isolate*, V8InspectorClient*);
  ~V8InspectorImpl() override;

  v8::Isolate* isolate() const { return m_isolate; }
  V8InspectorClient* client() { return m_client; }
  V8Debugger* debugger() { return m_debugger.get(); }
  int contextGroupId(v8::Local<v8::Context>) const;
  int contextGroupId(int contextId) const;

  v8::MaybeLocal<v8::Value> compileAndRunInternalScript(
      v8::Local<v8::Context>, v8::Local<v8::String>) override;
  v8::MaybeLocal<v8::Script> compileScript(v8::Local<v8::Context>,
                                           const String16& code,
                                           const String16& fileName);
  v8::Local<v8::Context> regexContext();

  // V8Inspector implementation.
  std::unique_ptr<V8InspectorSession> connect(int contextGroupId,
                                              V8Inspector::Channel*,
                                              const StringView& state) override;
  void contextCreated(const V8ContextInfo&) override;
  void contextDestroyed(v8::Local<v8::Context>) override;
  void contextCollected(int contextGroupId, int contextId);
  void resetContextGroup(int contextGroupId) override;
  void idleStarted() override;
  void idleFinished() override;
  unsigned exceptionThrown(v8::Local<v8::Context>, const StringView& message,
                           v8::Local<v8::Value> exception,
                           const StringView& detailedMessage,
                           const StringView& url, unsigned lineNumber,
                           unsigned columnNumber, std::unique_ptr<V8StackTrace>,
                           int scriptId) override;
  void exceptionRevoked(v8::Local<v8::Context>, unsigned exceptionId,
                        const StringView& message) override;
  std::unique_ptr<V8StackTrace> createStackTrace(
      v8::Local<v8::StackTrace>) override;
  std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) override;
  void asyncTaskScheduled(const StringView& taskName, void* task,
                          bool recurring) override;
  void asyncTaskCanceled(void* task) override;
  void asyncTaskStarted(void* task) override;
  void asyncTaskFinished(void* task) override;
  void allAsyncTasksCanceled() override;

  V8StackTraceId storeCurrentStackTrace(const StringView& description) override;
  void externalAsyncTaskStarted(const V8StackTraceId& parent) override;
  void externalAsyncTaskFinished(const V8StackTraceId& parent) override;

  unsigned nextExceptionId() { return ++m_lastExceptionId; }
  void enableStackCapturingIfNeeded();
  void disableStackCapturingIfNeeded();
  void muteExceptions(int contextGroupId);
  void unmuteExceptions(int contextGroupId);
  V8ConsoleMessageStorage* ensureConsoleMessageStorage(int contextGroupId);
  bool hasConsoleMessageStorage(int contextGroupId);
  void discardInspectedContext(int contextGroupId, int contextId);
  void disconnect(V8InspectorSessionImpl*);
  V8InspectorSessionImpl* sessionById(int contextGroupId, int sessionId);
  InspectedContext* getContext(int groupId, int contextId) const;
  InspectedContext* getContext(int contextId) const;
  V8Console* console();
  void forEachContext(int contextGroupId,
                      std::function<void(InspectedContext*)> callback);
  void forEachSession(int contextGroupId,
                      std::function<void(V8InspectorSessionImpl*)> callback);

 private:
  v8::Isolate* m_isolate;
  V8InspectorClient* m_client;
  std::unique_ptr<V8Debugger> m_debugger;
  v8::Global<v8::Context> m_regexContext;
  int m_capturingStackTracesCount;
  unsigned m_lastExceptionId;
  int m_lastContextId;
  int m_lastSessionId = 0;

  using MuteExceptionsMap = protocol::HashMap<int, int>;
  MuteExceptionsMap m_muteExceptionsMap;

  using ContextByIdMap =
      protocol::HashMap<int, std::unique_ptr<InspectedContext>>;
  using ContextsByGroupMap =
      protocol::HashMap<int, std::unique_ptr<ContextByIdMap>>;
  ContextsByGroupMap m_contexts;

  // contextGroupId -> sessionId -> session
  protocol::HashMap<int, std::map<int, V8InspectorSessionImpl*>> m_sessions;

  using ConsoleStorageMap =
      protocol::HashMap<int, std::unique_ptr<V8ConsoleMessageStorage>>;
  ConsoleStorageMap m_consoleStorageMap;

  protocol::HashMap<int, int> m_contextIdToGroupIdMap;

  std::unique_ptr<V8Console> m_console;

  DISALLOW_COPY_AND_ASSIGN(V8InspectorImpl);
};

}  // namespace v8_inspector

#endif  // V8_INSPECTOR_V8INSPECTORIMPL_H_
