/*
 *  Copyright 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/pc/quicdatatransport.h"

#include "webrtc/p2p/quic/quictransportchannel.h"
#include "webrtc/p2p/quic/reliablequicstream.h"
#include "webrtc/rtc_base/bind.h"
#include "webrtc/rtc_base/logging.h"

namespace webrtc {

QuicDataTransport::QuicDataTransport(
    rtc::Thread* signaling_thread,
    rtc::Thread* worker_thread,
    rtc::Thread* network_thread,
    cricket::TransportController* transport_controller)
    : signaling_thread_(signaling_thread),
      worker_thread_(worker_thread),
      network_thread_(network_thread),
      transport_controller_(transport_controller) {
  RTC_DCHECK(signaling_thread_);
  RTC_DCHECK(worker_thread_);
  RTC_DCHECK(network_thread_);
}

QuicDataTransport::~QuicDataTransport() {
  DestroyTransportChannel(quic_transport_channel_);
  LOG(LS_INFO) << "Destroyed the QUIC data transport.";
}

bool QuicDataTransport::SetTransport(const std::string& transport_name) {
  if (transport_name_ == transport_name) {
    // Nothing to do if transport name isn't changing
    return true;
  }

  cricket::QuicTransportChannel* transport_channel =
      CreateTransportChannel(transport_name);
  if (!SetTransportChannel(transport_channel)) {
    DestroyTransportChannel(transport_channel);
    return false;
  }

  transport_name_ = transport_name;
  return true;
}

bool QuicDataTransport::SetTransportChannel(
    cricket::QuicTransportChannel* channel) {
  if (!channel) {
    LOG(LS_ERROR) << "|channel| is NULL. Cannot set transport channel.";
    return false;
  }
  if (quic_transport_channel_) {
    if (channel == quic_transport_channel_) {
      LOG(LS_WARNING) << "Ignoring duplicate transport channel.";
      return true;
    }
    LOG(LS_ERROR) << "|channel| does not match existing transport channel.";
    return false;
  }

  LOG(LS_INFO) << "Setting QuicTransportChannel for QuicDataTransport";
  quic_transport_channel_ = channel;
  quic_transport_channel_->SignalIncomingStream.connect(
      this, &QuicDataTransport::OnIncomingStream);
  bool success = true;
  for (const auto& kv : data_channel_by_id_) {
    rtc::scoped_refptr<QuicDataChannel> data_channel = kv.second;
    if (!data_channel->SetTransportChannel(quic_transport_channel_)) {
      LOG(LS_ERROR)
          << "Cannot set QUIC transport channel for QUIC data channel "
          << kv.first;
      success = false;
    }
  }
  return success;
}

rtc::scoped_refptr<DataChannelInterface> QuicDataTransport::CreateDataChannel(
    const std::string& label,
    const DataChannelInit* config) {
  if (config == nullptr) {
    return nullptr;
  }
  if (data_channel_by_id_.find(config->id) != data_channel_by_id_.end()) {
    LOG(LS_ERROR) << "QUIC data channel already exists with id " << config->id;
    return nullptr;
  }
  rtc::scoped_refptr<QuicDataChannel> data_channel(new QuicDataChannel(
      signaling_thread_, worker_thread_, network_thread_, label, *config));
  if (quic_transport_channel_) {
    if (!data_channel->SetTransportChannel(quic_transport_channel_)) {
      LOG(LS_ERROR)
          << "Cannot set QUIC transport channel for QUIC data channel "
          << config->id;
    }
  }

  data_channel_by_id_[data_channel->id()] = data_channel;
  return data_channel;
}

void QuicDataTransport::DestroyDataChannel(int id) {
  data_channel_by_id_.erase(id);
}

bool QuicDataTransport::HasDataChannel(int id) const {
  return data_channel_by_id_.find(id) != data_channel_by_id_.end();
}

bool QuicDataTransport::HasDataChannels() const {
  return !data_channel_by_id_.empty();
}

// Called when a QUIC stream is created for incoming data.
void QuicDataTransport::OnIncomingStream(cricket::ReliableQuicStream* stream) {
  RTC_DCHECK(stream != nullptr);
  quic_stream_by_id_[stream->id()] = stream;
  stream->SignalDataReceived.connect(this, &QuicDataTransport::OnDataReceived);
}

// Called when the first QUIC stream frame is received for incoming data.
void QuicDataTransport::OnDataReceived(net::QuicStreamId id,
                                       const char* data,
                                       size_t len) {
  const auto& quic_stream_kv = quic_stream_by_id_.find(id);
  if (quic_stream_kv == quic_stream_by_id_.end()) {
    RTC_NOTREACHED();
    return;
  }
  cricket::ReliableQuicStream* stream = quic_stream_kv->second;
  stream->SignalDataReceived.disconnect(this);
  quic_stream_by_id_.erase(id);
  // Read the data channel ID and message ID.
  int data_channel_id;
  uint64_t message_id;
  size_t bytes_read;
  if (!ParseQuicDataMessageHeader(data, len, &data_channel_id, &message_id,
                                  &bytes_read)) {
    LOG(LS_ERROR) << "Could not read QUIC message header from QUIC stream "
                  << id;
    return;
  }
  data += bytes_read;
  len -= bytes_read;
  // Retrieve the data channel which will handle the message.
  const auto& data_channel_kv = data_channel_by_id_.find(data_channel_id);
  if (data_channel_kv == data_channel_by_id_.end()) {
    // TODO(mikescarlett): Implement OPEN message to create a new
    // QuicDataChannel when messages are received for a nonexistent ID.
    LOG(LS_ERROR) << "Data was received for QUIC data channel "
                  << data_channel_id
                  << " but it is not registered to the QuicDataTransport.";
    return;
  }
  QuicDataChannel* data_channel = data_channel_kv->second;
  QuicDataChannel::Message message;
  message.id = message_id;
  message.buffer = rtc::CopyOnWriteBuffer(data, len);
  message.stream = stream;
  data_channel->OnIncomingMessage(std::move(message));
}

cricket::QuicTransportChannel* QuicDataTransport::CreateTransportChannel(
    const std::string& transport_name) {
  DCHECK(transport_controller_->quic());

  cricket::TransportChannel* transport_channel =
      network_thread_->Invoke<cricket::TransportChannel*>(
          RTC_FROM_HERE,
          rtc::Bind(&cricket::TransportController::CreateTransportChannel_n,
                    transport_controller_, transport_name,
                    cricket::ICE_CANDIDATE_COMPONENT_DEFAULT));
  return static_cast<cricket::QuicTransportChannel*>(transport_channel);
}

void QuicDataTransport::DestroyTransportChannel(
    cricket::TransportChannel* transport_channel) {
  if (transport_channel) {
    network_thread_->Invoke<void>(
        RTC_FROM_HERE,
        rtc::Bind(&cricket::TransportController::DestroyTransportChannel_n,
                  transport_controller_, transport_channel->transport_name(),
                  cricket::ICE_CANDIDATE_COMPONENT_DEFAULT));
  }
}

}  // namespace webrtc
