// Copyright 2014 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 "remoting/protocol/fake_stream_socket.h"

#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace remoting {
namespace protocol {

FakeStreamSocket::FakeStreamSocket()
    : task_runner_(base::ThreadTaskRunnerHandle::Get()), weak_factory_(this) {}

FakeStreamSocket::~FakeStreamSocket() {
  EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  if (peer_socket_) {
    task_runner_->PostTask(
        FROM_HERE, base::Bind(&FakeStreamSocket::SetReadError, peer_socket_,
                              net::ERR_CONNECTION_CLOSED));
  }
}

void FakeStreamSocket::AppendInputData(const std::string& data) {
  EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  input_data_.insert(input_data_.end(), data.begin(), data.end());
  // Complete pending read if any.
  if (!read_callback_.is_null()) {
    int result = std::min(read_buffer_size_,
                          static_cast<int>(input_data_.size() - input_pos_));
    EXPECT_GT(result, 0);
    memcpy(read_buffer_->data(),
           &(*input_data_.begin()) + input_pos_, result);
    input_pos_ += result;
    read_buffer_ = nullptr;

    base::ResetAndReturn(&read_callback_).Run(result);
  }
}

void FakeStreamSocket::SetReadError(int error) {
  EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  // Complete pending read if any.
  if (!read_callback_.is_null()) {
    base::ResetAndReturn(&read_callback_).Run(error);
  } else {
    next_read_error_ = error;
  }
}

void FakeStreamSocket::PairWith(FakeStreamSocket* peer_socket) {
  EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  peer_socket_ = peer_socket->GetWeakPtr();
  peer_socket->peer_socket_ = GetWeakPtr();
}

base::WeakPtr<FakeStreamSocket> FakeStreamSocket::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

int FakeStreamSocket::Read(const scoped_refptr<net::IOBuffer>& buf,
                           int buf_len,
                           const net::CompletionCallback& callback) {
  EXPECT_TRUE(task_runner_->BelongsToCurrentThread());

  if (input_pos_ < static_cast<int>(input_data_.size())) {
    int result = std::min(buf_len,
                          static_cast<int>(input_data_.size()) - input_pos_);
    memcpy(buf->data(), &(*input_data_.begin()) + input_pos_, result);
    input_pos_ += result;
    return result;
  } else if (next_read_error_.has_value()) {
    int r = next_read_error_.value();
    next_read_error_.reset();
    return r;
  } else {
    read_buffer_ = buf;
    read_buffer_size_ = buf_len;
    read_callback_ = callback;
    return net::ERR_IO_PENDING;
  }
}

int FakeStreamSocket::Write(
    const scoped_refptr<net::IOBuffer>& buf,
    int buf_len,
    const net::CompletionCallback& callback,
    const net::NetworkTrafficAnnotationTag& traffic_annotation) {
  EXPECT_TRUE(task_runner_->BelongsToCurrentThread());
  EXPECT_FALSE(write_pending_);

  if (write_limit_ > 0)
    buf_len = std::min(write_limit_, buf_len);

  if (async_write_) {
    task_runner_->PostTask(FROM_HERE, base::Bind(
        &FakeStreamSocket::DoAsyncWrite, weak_factory_.GetWeakPtr(),
        scoped_refptr<net::IOBuffer>(buf), buf_len, callback));
    write_pending_ = true;
    return net::ERR_IO_PENDING;
  } else {
    if (next_write_error_ != net::OK) {
      int r = next_write_error_;
      next_write_error_ = net::OK;
      return r;
    }

    DoWrite(buf, buf_len);
    return buf_len;
  }
}

void FakeStreamSocket::DoAsyncWrite(const scoped_refptr<net::IOBuffer>& buf,
                                    int buf_len,
                                    const net::CompletionCallback& callback) {
  write_pending_ = false;

  if (next_write_error_ != net::OK) {
    int r = next_write_error_;
    next_write_error_ = net::OK;
    callback.Run(r);
    return;
  }

  DoWrite(buf.get(), buf_len);
  callback.Run(buf_len);
}

void FakeStreamSocket::DoWrite(const scoped_refptr<net::IOBuffer>& buf,
                               int buf_len) {
  written_data_.insert(written_data_.end(),
                       buf->data(), buf->data() + buf_len);

  if (peer_socket_) {
    task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&FakeStreamSocket::AppendInputData,
                   peer_socket_,
                   std::string(buf->data(), buf->data() + buf_len)));
  }
}

FakeStreamChannelFactory::FakeStreamChannelFactory()
    : task_runner_(base::ThreadTaskRunnerHandle::Get()),
      weak_factory_(this) {
}

FakeStreamChannelFactory::~FakeStreamChannelFactory() = default;

FakeStreamSocket* FakeStreamChannelFactory::GetFakeChannel(
    const std::string& name) {
  return channels_[name].get();
}

void FakeStreamChannelFactory::PairWith(
    FakeStreamChannelFactory* peer_factory) {
  peer_factory_ = peer_factory->weak_factory_.GetWeakPtr();
  peer_factory->peer_factory_ = weak_factory_.GetWeakPtr();
}

void FakeStreamChannelFactory::CreateChannel(
    const std::string& name,
    const ChannelCreatedCallback& callback) {
  std::unique_ptr<FakeStreamSocket> channel(new FakeStreamSocket());
  channels_[name] = channel->GetWeakPtr();
  channel->set_async_write(async_write_);

  if (peer_factory_) {
    FakeStreamSocket* peer_channel = peer_factory_->GetFakeChannel(name);
    if (peer_channel)
      channel->PairWith(peer_channel);
  }

  if (fail_create_)
    channel.reset();

  if (asynchronous_create_) {
    task_runner_->PostTask(FROM_HERE, base::Bind(
        &FakeStreamChannelFactory::NotifyChannelCreated,
        weak_factory_.GetWeakPtr(), base::Passed(&channel), name, callback));
  } else {
    NotifyChannelCreated(std::move(channel), name, callback);
  }
}

void FakeStreamChannelFactory::NotifyChannelCreated(
    std::unique_ptr<FakeStreamSocket> owned_channel,
    const std::string& name,
    const ChannelCreatedCallback& callback) {
  if (channels_.find(name) != channels_.end())
    callback.Run(std::move(owned_channel));
}

void FakeStreamChannelFactory::CancelChannelCreation(const std::string& name) {
  channels_.erase(name);
}

}  // namespace protocol
}  // namespace remoting
