/*
 *  Copyright 2013 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.
 */

#ifndef PC_TEST_FAKEDATACHANNELPROVIDER_H_
#define PC_TEST_FAKEDATACHANNELPROVIDER_H_

#include <set>

#include "pc/datachannel.h"
#include "rtc_base/checks.h"

class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface {
 public:
  FakeDataChannelProvider()
      : send_blocked_(false),
        transport_available_(false),
        ready_to_send_(false),
        transport_error_(false) {}
  virtual ~FakeDataChannelProvider() {}

  bool SendData(const cricket::SendDataParams& params,
                const rtc::CopyOnWriteBuffer& payload,
                cricket::SendDataResult* result) override {
    RTC_CHECK(ready_to_send_);
    RTC_CHECK(transport_available_);
    if (send_blocked_) {
      *result = cricket::SDR_BLOCK;
      return false;
    }

    if (transport_error_ || payload.size() == 0) {
      *result = cricket::SDR_ERROR;
      return false;
    }

    last_send_data_params_ = params;
    return true;
  }

  bool ConnectDataChannel(webrtc::DataChannel* data_channel) override {
    RTC_CHECK(connected_channels_.find(data_channel) ==
              connected_channels_.end());
    if (!transport_available_) {
      return false;
    }
    RTC_LOG(LS_INFO) << "DataChannel connected " << data_channel;
    connected_channels_.insert(data_channel);
    return true;
  }

  void DisconnectDataChannel(webrtc::DataChannel* data_channel) override {
    RTC_CHECK(connected_channels_.find(data_channel) !=
              connected_channels_.end());
    RTC_LOG(LS_INFO) << "DataChannel disconnected " << data_channel;
    connected_channels_.erase(data_channel);
  }

  void AddSctpDataStream(int sid) override {
    RTC_CHECK(sid >= 0);
    if (!transport_available_) {
      return;
    }
    send_ssrcs_.insert(sid);
    recv_ssrcs_.insert(sid);
  }

  void RemoveSctpDataStream(int sid) override {
    RTC_CHECK(sid >= 0);
    send_ssrcs_.erase(sid);
    recv_ssrcs_.erase(sid);
    // Unlike the real SCTP transport, act like the closing procedure finished
    // instantly, doing the same snapshot thing as below.
    for (webrtc::DataChannel* ch : std::set<webrtc::DataChannel*>(
             connected_channels_.begin(), connected_channels_.end())) {
      if (connected_channels_.count(ch)) {
        ch->OnClosingProcedureComplete(sid);
      }
    }
  }

  bool ReadyToSendData() const override { return ready_to_send_; }

  // Set true to emulate the SCTP stream being blocked by congestion control.
  void set_send_blocked(bool blocked) {
    send_blocked_ = blocked;
    if (!blocked) {
      // Take a snapshot of the connected channels and check to see whether
      // each value is still in connected_channels_ before calling
      // OnChannelReady().  This avoids problems where the set gets modified
      // in response to OnChannelReady().
      for (webrtc::DataChannel* ch : std::set<webrtc::DataChannel*>(
               connected_channels_.begin(), connected_channels_.end())) {
        if (connected_channels_.count(ch)) {
          ch->OnChannelReady(true);
        }
      }
    }
  }

  // Set true to emulate the transport channel creation, e.g. after
  // setLocalDescription/setRemoteDescription called with data content.
  void set_transport_available(bool available) {
    transport_available_ = available;
  }

  // Set true to emulate the transport ReadyToSendData signal when the transport
  // becomes writable for the first time.
  void set_ready_to_send(bool ready) {
    RTC_CHECK(transport_available_);
    ready_to_send_ = ready;
    if (ready) {
      std::set<webrtc::DataChannel*>::iterator it;
      for (it = connected_channels_.begin(); it != connected_channels_.end();
           ++it) {
        (*it)->OnChannelReady(true);
      }
    }
  }

  void set_transport_error() { transport_error_ = true; }

  cricket::SendDataParams last_send_data_params() const {
    return last_send_data_params_;
  }

  bool IsConnected(webrtc::DataChannel* data_channel) const {
    return connected_channels_.find(data_channel) != connected_channels_.end();
  }

  bool IsSendStreamAdded(uint32_t stream) const {
    return send_ssrcs_.find(stream) != send_ssrcs_.end();
  }

  bool IsRecvStreamAdded(uint32_t stream) const {
    return recv_ssrcs_.find(stream) != recv_ssrcs_.end();
  }

 private:
  cricket::SendDataParams last_send_data_params_;
  bool send_blocked_;
  bool transport_available_;
  bool ready_to_send_;
  bool transport_error_;
  std::set<webrtc::DataChannel*> connected_channels_;
  std::set<uint32_t> send_ssrcs_;
  std::set<uint32_t> recv_ssrcs_;
};
#endif  // PC_TEST_FAKEDATACHANNELPROVIDER_H_
