// Copyright (c) 2018 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 "chrome/chrome_cleaner/http/mock_http_agent_factory.h"

#include <stdint.h>

#include <algorithm>
#include <memory>
#include <string>
#include <vector>

#include "base/logging.h"
#include "chrome/chrome_cleaner/http/http_agent.h"
#include "chrome/chrome_cleaner/http/http_agent_factory.h"
#include "chrome/chrome_cleaner/http/http_response.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace chrome_cleaner {

namespace {

// Class that provides a response based on how the MockHttpAgentConfig is
// configured.
class MockHttpResponse : public chrome_cleaner::HttpResponse {
 public:
  explicit MockHttpResponse(MockHttpAgentConfig* config) : config_(config) {
    DCHECK(config);
  }

  ~MockHttpResponse() override = default;

  // chrome_cleaner::HttpResponse:
  bool GetStatusCode(uint16_t* status_code) override {
    if (config_->GetCurrentCalls().get_status_code_succeeds) {
      *status_code = static_cast<uint16_t>(
          config_->GetCurrentCalls().get_status_code_result);
    }
    return config_->GetCurrentCalls().get_status_code_succeeds;
  }

  bool GetContentLength(bool* has_content_length,
                        size_t* content_length) override {
    ADD_FAILURE() << "This method should not be called.";
    return false;
  }

  bool GetContentType(bool* has_content_type,
                      base::string16* content_type) override {
    ADD_FAILURE() << "This method should not be called.";
    return false;
  }

  bool HasData(bool* has_data) override {
    if (config_->GetCurrentCalls().has_data_succeeds)
      *has_data = !config_->GetCurrentCalls().read_data_result.empty();
    return config_->GetCurrentCalls().has_data_succeeds;
  }

  bool ReadData(char* buffer, size_t* count) override {
    MockHttpAgentConfig::Calls& calls = config_->GetCurrentCalls();

    bool succeeds = calls.read_data_succeeds_by_default;
    if (!calls.read_data_success_sequence.empty()) {
      succeeds = calls.read_data_success_sequence[0];
      calls.read_data_success_sequence.erase(
          calls.read_data_success_sequence.begin());
    }

    if (succeeds)
      config_->ReadData(buffer, count);
    return succeeds;
  }

 private:
  MockHttpAgentConfig* config_{nullptr};

  DISALLOW_COPY_AND_ASSIGN(MockHttpResponse);
};

// Class that acts as an HttpAgent based on how the MockHttpAgentConfig is
// configured.
class MockHttpAgent : public chrome_cleaner::HttpAgent {
 public:
  explicit MockHttpAgent(MockHttpAgentConfig* config) : config_(config) {
    DCHECK(config);
  }

  ~MockHttpAgent() override = default;

  // chrome_cleaner::HttpAgent:
  std::unique_ptr<chrome_cleaner::HttpResponse> Post(
      const base::string16& host,
      uint16_t port,
      const base::string16& path,
      bool secure,
      const base::string16& extra_headers,
      const std::string& body) override {
    const bool post_succeeds = config_->GetCurrentCalls().request_succeeds;
    MockHttpAgentConfig::RequestData post_data;
    post_data.host = host;
    post_data.port = port;
    post_data.path = path;
    post_data.secure = secure;
    post_data.extra_headers = extra_headers;
    post_data.body = body;
    config_->AddRequestData(post_data);

    if (post_succeeds)
      return std::unique_ptr<MockHttpResponse>(new MockHttpResponse(config_));
    return std::unique_ptr<MockHttpResponse>();
  }

  // chrome_cleaner::HttpAgent:
  std::unique_ptr<chrome_cleaner::HttpResponse> Get(
      const base::string16& host,
      uint16_t port,
      const base::string16& path,
      bool secure,
      const base::string16& extra_headers) override {
    const bool get_succeeds = config_->GetCurrentCalls().request_succeeds;
    MockHttpAgentConfig::RequestData get_data;
    get_data.host = host;
    get_data.port = port;
    get_data.path = path;
    get_data.secure = secure;
    get_data.extra_headers = extra_headers;
    config_->AddRequestData(get_data);

    if (get_succeeds)
      return std::unique_ptr<MockHttpResponse>(new MockHttpResponse(config_));
    return std::unique_ptr<MockHttpResponse>();
  }

 private:
  MockHttpAgentConfig* config_{nullptr};

  DISALLOW_COPY_AND_ASSIGN(MockHttpAgent);
};

}  // namespace

MockHttpAgentConfig::Calls::Calls(HttpStatus status)
    : get_status_code_result(status) {}

MockHttpAgentConfig::Calls::Calls(const Calls& other) = default;

MockHttpAgentConfig::Calls::~Calls() = default;

MockHttpAgentConfig::Calls& MockHttpAgentConfig::Calls::operator=(
    const MockHttpAgentConfig::Calls& other) = default;

MockHttpAgentConfig::RequestData::RequestData() = default;

MockHttpAgentConfig::RequestData::RequestData(const RequestData& other) =
    default;

MockHttpAgentConfig::RequestData::~RequestData() = default;

MockHttpAgentConfig::RequestData& MockHttpAgentConfig::RequestData::operator=(
    const MockHttpAgentConfig::RequestData& other) = default;

MockHttpAgentConfig::MockHttpAgentConfig() = default;

MockHttpAgentConfig::~MockHttpAgentConfig() = default;

size_t MockHttpAgentConfig::AddCalls(const Calls& calls) {
  calls_.push_back(calls);
  return calls_.size() - 1;
}

MockHttpAgentConfig::Calls& MockHttpAgentConfig::GetCurrentCalls() {
  if (current_index_ >= calls_.size()) {
    static Calls default_calls(HttpStatus::kOk);
    ADD_FAILURE() << "Did not expect more than " << calls_.size() << " tries";
    return default_calls;
  }
  return calls_[current_index_];
}

void MockHttpAgentConfig::ReadData(char* buffer, size_t* count) {
  if (current_index_ >= calls_.size()) {
    ADD_FAILURE() << "Reading data for an unexpected call";
    *count = 0;
    return;
  }
  Calls& calls = calls_[current_index_];
  *count = std::min(*count, calls.read_data_result.size());
  memcpy(buffer, calls.read_data_result.c_str(), *count);
  calls.read_data_result = calls.read_data_result.substr(*count);
}

void MockHttpAgentConfig::AddRequestData(const RequestData& request_data) {
  ASSERT_EQ(request_data_.size(), current_index_)
      << "MockHttpAgentConfig does not support creating multiple agents "
      << "without calling Post or Get on each before creating the next one. "
      << "Suggest adding support to MockHttpAgentConfig for that if necessary, "
      << "or updating your code to avoid this.";
  request_data_.push_back(request_data);
}

MockHttpAgentFactory::MockHttpAgentFactory(MockHttpAgentConfig* config)
    : config_(config) {
  DCHECK(config);
}

std::unique_ptr<chrome_cleaner::HttpAgent>
MockHttpAgentFactory::CreateHttpAgent() {
  // Set the configuration index to the next one (one per HttpAgent).
  if (config_->current_index_ == MockHttpAgentConfig::kInvalidIndex)
    config_->current_index_ = 0;
  else
    ++config_->current_index_;

  return std::unique_ptr<MockHttpAgent>(new MockHttpAgent(config_));
}

}  // namespace chrome_cleaner
