// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/renderer/display_source_custom_bindings.h"

#include <stdint.h>

#include "base/bind.h"
#include "content/public/renderer/v8_value_converter.h"
#include "extensions/renderer/extension_bindings_system.h"
#include "extensions/renderer/script_context.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/public/web/web_dom_media_stream_track.h"
#include "v8/include/v8.h"

namespace extensions {

namespace {
const char kErrorNotSupported[] = "Not supported";
const char kInvalidStreamArgs[] = "Invalid stream arguments";
const char kSessionAlreadyStarted[] = "The session has been already started";
const char kSessionAlreadyTerminating[] = "The session is already terminating";
const char kSessionNotFound[] = "Session not found";
}  // namespace

DisplaySourceCustomBindings::DisplaySourceCustomBindings(
    ScriptContext* context,
    ExtensionBindingsSystem* bindings_system)
    : ObjectBackedNativeHandler(context),
      bindings_system_(bindings_system),
      weak_factory_(this) {}

DisplaySourceCustomBindings::~DisplaySourceCustomBindings() {}

void DisplaySourceCustomBindings::AddRoutes() {
  RouteHandlerFunction("StartSession", "displaySource",
                       base::Bind(&DisplaySourceCustomBindings::StartSession,
                                  weak_factory_.GetWeakPtr()));
  RouteHandlerFunction(
      "TerminateSession", "displaySource",
      base::Bind(&DisplaySourceCustomBindings::TerminateSession,
                 weak_factory_.GetWeakPtr()));
}

void DisplaySourceCustomBindings::Invalidate() {
  session_map_.clear();
  weak_factory_.InvalidateWeakPtrs();
  ObjectBackedNativeHandler::Invalidate();
}

namespace {

v8::Local<v8::Value> GetChildValue(v8::Local<v8::Object> value,
                                   const std::string& key_name,
                                   v8::Isolate* isolate) {
  v8::Local<v8::Array> property_names(value->GetOwnPropertyNames());
  for (uint32_t i = 0; i < property_names->Length(); ++i) {
    v8::Local<v8::Value> key(property_names->Get(i));
    if (key_name == *v8::String::Utf8Value(isolate, key)) {
      v8::TryCatch try_catch(isolate);
      v8::Local<v8::Value> child_v8 = value->Get(key);
      if (try_catch.HasCaught()) {
        return v8::Null(isolate);
      }
      return child_v8;
    }
  }

  return v8::Null(isolate);
}

int32_t GetCallbackId() {
  static int32_t sCallId = 0;
  return ++sCallId;
}

}  // namespace

void DisplaySourceCustomBindings::StartSession(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK_EQ(1, args.Length());
  CHECK(args[0]->IsObject());

  v8::Isolate* isolate = context()->isolate();
  v8::Local<v8::Object> start_info = args[0].As<v8::Object>();

  v8::Local<v8::Value> sink_id_val =
      GetChildValue(start_info, "sinkId", isolate);
  CHECK(sink_id_val->IsInt32());
  const int sink_id = sink_id_val->ToInt32(isolate)->Value();
  if (GetDisplaySession(sink_id)) {
    isolate->ThrowException(v8::Exception::Error(
        v8::String::NewFromUtf8(isolate, kSessionAlreadyStarted,
                                v8::NewStringType::kNormal)
            .ToLocalChecked()));
    return;
  }

  v8::Local<v8::Value> video_stream_val =
      GetChildValue(start_info, "videoTrack", isolate);
  v8::Local<v8::Value> audio_stream_val =
      GetChildValue(start_info, "audioTrack", isolate);

  if ((video_stream_val->IsNull() || video_stream_val->IsUndefined()) &&
      (audio_stream_val->IsNull() || audio_stream_val->IsUndefined())) {
    isolate->ThrowException(v8::Exception::Error(
        v8::String::NewFromUtf8(isolate, kInvalidStreamArgs,
                                v8::NewStringType::kNormal)
            .ToLocalChecked()));
    return;
  }

  blink::WebMediaStreamTrack audio_track, video_track;

  if (!video_stream_val->IsNull() && !video_stream_val->IsUndefined()) {
    CHECK(video_stream_val->IsObject());
    video_track = blink::WebDOMMediaStreamTrack::FromV8Value(video_stream_val)
                      .Component();
    if (video_track.IsNull()) {
      isolate->ThrowException(v8::Exception::Error(
          v8::String::NewFromUtf8(isolate, kInvalidStreamArgs,
                                  v8::NewStringType::kNormal)
              .ToLocalChecked()));
      return;
    }
  }
  if (!audio_stream_val->IsNull() && !audio_stream_val->IsUndefined()) {
    CHECK(audio_stream_val->IsObject());
    audio_track = blink::WebDOMMediaStreamTrack::FromV8Value(audio_stream_val)
                      .Component();
    if (audio_track.IsNull()) {
      isolate->ThrowException(v8::Exception::Error(
          v8::String::NewFromUtf8(isolate, kInvalidStreamArgs,
                                  v8::NewStringType::kNormal)
              .ToLocalChecked()));
      return;
    }
  }

  std::unique_ptr<DisplaySourceAuthInfo> auth_info;
  v8::Local<v8::Value> auth_info_v8_val =
      GetChildValue(start_info, "authenticationInfo", isolate);
  if (!auth_info_v8_val->IsNull()) {
    CHECK(auth_info_v8_val->IsObject());
    std::unique_ptr<base::Value> auth_info_val =
        content::V8ValueConverter::Create()->FromV8Value(
            auth_info_v8_val, context()->v8_context());
    CHECK(auth_info_val);
    auth_info = DisplaySourceAuthInfo::FromValue(*auth_info_val);
  }

  DisplaySourceSessionParams session_params;
  session_params.sink_id = sink_id;
  session_params.video_track = video_track;
  session_params.audio_track = audio_track;
  session_params.render_frame = context()->GetRenderFrame();
  if (auth_info) {
    session_params.auth_method = auth_info->method;
    session_params.auth_data = auth_info->data ? *auth_info->data : "";
  }
  std::unique_ptr<DisplaySourceSession> session =
      DisplaySourceSessionFactory::CreateSession(session_params);
  if (!session) {
    isolate->ThrowException(v8::Exception::Error(
        v8::String::NewFromUtf8(isolate, kErrorNotSupported,
                                v8::NewStringType::kNormal)
            .ToLocalChecked()));
    return;
  }

  auto on_terminated_callback =
      base::Bind(&DisplaySourceCustomBindings::OnSessionTerminated,
                 weak_factory_.GetWeakPtr(), sink_id);
  auto on_error_callback =
      base::Bind(&DisplaySourceCustomBindings::OnSessionError,
                 weak_factory_.GetWeakPtr(), sink_id);
  session->SetNotificationCallbacks(on_terminated_callback, on_error_callback);

  int32_t call_id = GetCallbackId();
  args.GetReturnValue().Set(call_id);

  auto on_call_completed =
      base::Bind(&DisplaySourceCustomBindings::OnSessionStarted,
                 weak_factory_.GetWeakPtr(), sink_id, call_id);
  session->Start(on_call_completed);
  session_map_.insert(std::make_pair(sink_id, std::move(session)));
}

void DisplaySourceCustomBindings::TerminateSession(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK_EQ(1, args.Length());
  CHECK(args[0]->IsInt32());

  v8::Isolate* isolate = context()->isolate();
  int sink_id = args[0]->ToInt32(args.GetIsolate())->Value();
  DisplaySourceSession* session = GetDisplaySession(sink_id);
  if (!session) {
    isolate->ThrowException(
        v8::Exception::Error(v8::String::NewFromUtf8(isolate, kSessionNotFound,
                                                     v8::NewStringType::kNormal)
                                 .ToLocalChecked()));
    return;
  }

  DisplaySourceSession::State state = session->state();
  DCHECK_NE(state, DisplaySourceSession::Idle);
  if (state == DisplaySourceSession::Establishing) {
    // 'session started' callback has not yet been invoked.
    // This session is not existing for the user.
    isolate->ThrowException(
        v8::Exception::Error(v8::String::NewFromUtf8(isolate, kSessionNotFound,
                                                     v8::NewStringType::kNormal)
                                 .ToLocalChecked()));
    return;
  }

  if (state == DisplaySourceSession::Terminating) {
    isolate->ThrowException(v8::Exception::Error(
        v8::String::NewFromUtf8(isolate, kSessionAlreadyTerminating,
                                v8::NewStringType::kNormal)
            .ToLocalChecked()));
    return;
  }

  int32_t call_id = GetCallbackId();
  args.GetReturnValue().Set(call_id);

  auto on_call_completed =
      base::Bind(&DisplaySourceCustomBindings::OnCallCompleted,
                 weak_factory_.GetWeakPtr(), call_id);
  // The session will get removed from session_map_ in OnSessionTerminated.
  session->Terminate(on_call_completed);
}

void DisplaySourceCustomBindings::OnCallCompleted(
    int call_id,
    bool success,
    const std::string& error_message) {
  v8::Isolate* isolate = context()->isolate();
  ModuleSystem* module_system = context()->module_system();
  v8::HandleScope handle_scope(isolate);
  v8::Context::Scope context_scope(context()->v8_context());

  v8::Local<v8::Value> callback_args[2];
  callback_args[0] = v8::Integer::New(isolate, call_id);
  if (success)
    callback_args[1] = v8::Null(isolate);
  else
    callback_args[1] = v8::String::NewFromUtf8(isolate, error_message.c_str(),
                                               v8::NewStringType::kNormal)
                           .ToLocalChecked();

  module_system->CallModuleMethodSafe("displaySource", "callCompletionCallback",
                                      2, callback_args);
}

void DisplaySourceCustomBindings::OnSessionStarted(
    int sink_id,
    int call_id,
    bool success,
    const std::string& error_message) {
  CHECK(GetDisplaySession(sink_id));
  if (!success) {
    // Session has failed to start, removing it.
    session_map_.erase(sink_id);
  }
  OnCallCompleted(call_id, success, error_message);
}

void DisplaySourceCustomBindings::DispatchSessionTerminated(int sink_id) const {
  base::ListValue event_args;
  event_args.AppendInteger(sink_id);
  bindings_system_->DispatchEventInContext("displaySource.onSessionTerminated",
                                           &event_args, nullptr, context());
}

void DisplaySourceCustomBindings::DispatchSessionError(
    int sink_id,
    DisplaySourceErrorType type,
    const std::string& message) const {
  api::display_source::ErrorInfo error_info;
  error_info.type = type;
  if (!message.empty())
    error_info.description.reset(new std::string(message));

  base::ListValue event_args;
  event_args.AppendInteger(sink_id);
  event_args.Append(error_info.ToValue());
  bindings_system_->DispatchEventInContext(
      "displaySource.onSessionErrorOccured", &event_args, nullptr, context());
}

DisplaySourceSession* DisplaySourceCustomBindings::GetDisplaySession(
    int sink_id) const {
  auto iter = session_map_.find(sink_id);
  if (iter != session_map_.end())
    return iter->second.get();
  return nullptr;
}

void DisplaySourceCustomBindings::OnSessionTerminated(int sink_id) {
  CHECK(GetDisplaySession(sink_id));
  session_map_.erase(sink_id);
  DispatchSessionTerminated(sink_id);
}

void DisplaySourceCustomBindings::OnSessionError(int sink_id,
                                                 DisplaySourceErrorType type,
                                                 const std::string& message) {
  CHECK(GetDisplaySession(sink_id));
  DispatchSessionError(sink_id, type, message);
}

}  // extensions
