// Copyright 2015 The Weave 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 "src/device_registration_info.h"

#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/values.h>
#include <gtest/gtest.h>
#include <weave/provider/test/fake_task_runner.h>
#include <weave/provider/test/mock_config_store.h>
#include <weave/provider/test/mock_http_client.h>

#include "src/bind_lambda.h"
#include "src/commands/command_manager.h"
#include "src/commands/unittest_utils.h"
#include "src/http_constants.h"
#include "src/states/mock_state_change_queue_interface.h"
#include "src/states/state_manager.h"

using testing::_;
using testing::AtLeast;
using testing::Invoke;
using testing::InvokeWithoutArgs;
using testing::Mock;
using testing::Return;
using testing::ReturnRef;
using testing::ReturnRefOfCopy;
using testing::SaveArg;
using testing::StrictMock;
using testing::WithArgs;

namespace weave {

using test::CreateDictionaryValue;
using test::CreateValue;
using provider::test::MockHttpClient;
using provider::test::MockHttpClientResponse;
using provider::HttpClient;

namespace {

namespace test_data {

const char kServiceURL[] = "http://gcd.server.com/";
const char kOAuthURL[] = "http://oauth.server.com/";
const char kApiKey[] = "GOadRdTf9FERf0k4w6EFOof56fUJ3kFDdFL3d7f";
const char kClientId[] =
    "123543821385-sfjkjshdkjhfk234sdfsdfkskd"
    "fkjh7f.apps.googleusercontent.com";
const char kClientSecret[] = "5sdGdGlfolGlrFKfdFlgP6FG";
const char kDeviceId[] = "4a7ea2d1-b331-1e1f-b206-e863c7635196";
const char kClaimTicketId[] = "RTcUE";
const char kAccessToken[] =
    "ya29.1.AADtN_V-dLUM-sVZ0qVjG9Dxm5NgdS9J"
    "Mx_JLUqhC9bED_YFjzHZtYt65ZzXCS35NMAeaVZ"
    "Dei530-w0yE2urpQ";
const char kRefreshToken[] =
    "1/zQmxR6PKNvhcxf9SjXUrCjcmCrcqRKXctc6cp"
    "1nI-GQ";
const char kRobotAccountAuthCode[] =
    "4/Mf_ujEhPejVhOq-OxW9F5cSOnWzx."
    "YgciVjTYGscRshQV0ieZDAqiTIjMigI";
const char kRobotAccountEmail[] =
    "6ed0b3f54f9bd619b942f4ad2441c252@"
    "clouddevices.gserviceaccount.com";

}  // namespace test_data

std::string GetFormField(const std::string& data, const std::string& name) {
  EXPECT_FALSE(data.empty());
  for (const auto& i : WebParamsDecode(data)) {
    if (i.first == name)
      return i.second;
  }
  return {};
}

std::unique_ptr<HttpClient::Response> ReplyWithJson(int status_code,
                                                    const base::Value& json) {
  std::string text;
  base::JSONWriter::WriteWithOptions(
      json, base::JSONWriter::OPTIONS_PRETTY_PRINT, &text);

  std::unique_ptr<MockHttpClientResponse> response{
      new StrictMock<MockHttpClientResponse>};
  EXPECT_CALL(*response, GetStatusCode())
      .Times(AtLeast(1))
      .WillRepeatedly(Return(status_code));
  EXPECT_CALL(*response, GetContentType())
      .Times(AtLeast(1))
      .WillRepeatedly(Return(http::kJsonUtf8));
  EXPECT_CALL(*response, GetData())
      .Times(AtLeast(1))
      .WillRepeatedly(Return(text));
  return std::move(response);
}

std::pair<std::string, std::string> GetAuthHeader() {
  return {http::kAuthorization,
          std::string("Bearer ") + test_data::kAccessToken};
}

std::pair<std::string, std::string> GetJsonHeader() {
  return {http::kContentType, http::kJsonUtf8};
}

std::pair<std::string, std::string> GetFormHeader() {
  return {http::kContentType, http::kWwwFormUrlEncoded};
}

}  // anonymous namespace

class DeviceRegistrationInfoTest : public ::testing::Test {
 protected:
  void SetUp() override {
    EXPECT_CALL(mock_state_change_queue_, GetLastStateChangeId())
        .WillRepeatedly(Return(0));
    EXPECT_CALL(mock_state_change_queue_, MockAddOnStateUpdatedCallback(_))
        .WillRepeatedly(Return(nullptr));

    command_manager_ = std::make_shared<CommandManager>();
    state_manager_ = std::make_shared<StateManager>(&mock_state_change_queue_);

    std::unique_ptr<Config> config{new Config{&config_store_}};
    config_ = config.get();
    dev_reg_.reset(new DeviceRegistrationInfo{command_manager_, state_manager_,
                                              std::move(config), &task_runner_,
                                              &http_client_, nullptr});

    ReloadDefaults();
  }

  void ReloadDefaults() {
    EXPECT_CALL(config_store_, LoadDefaults(_))
        .WillOnce(Invoke([](Settings* settings) {
          settings->client_id = test_data::kClientId;
          settings->client_secret = test_data::kClientSecret;
          settings->api_key = test_data::kApiKey;
          settings->oem_name = "Coffee Pot Maker";
          settings->model_name = "Pot v1";
          settings->name = "Coffee Pot";
          settings->description = "Easy to clean";
          settings->location = "Kitchen";
          settings->local_anonymous_access_role = AuthScope::kViewer;
          settings->model_id = "AAAAA";
          settings->oauth_url = test_data::kOAuthURL;
          settings->service_url = test_data::kServiceURL;
          return true;
        }));
    config_->Load();
    dev_reg_->Start();
  }

  void ReloadSettings() {
    base::DictionaryValue dict;
    dict.SetString("refresh_token", test_data::kRefreshToken);
    dict.SetString("cloud_id", test_data::kDeviceId);
    dict.SetString("robot_account", test_data::kRobotAccountEmail);
    std::string json_string;
    base::JSONWriter::WriteWithOptions(
        dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string);
    EXPECT_CALL(config_store_, LoadSettings()).WillOnce(Return(json_string));
    ReloadDefaults();
  }

  void PublishCommands(const base::ListValue& commands) {
    dev_reg_->PublishCommands(commands, nullptr);
  }

  bool RefreshAccessToken(ErrorPtr* error) const {
    bool succeeded = false;
    auto callback = [&succeeded, &error](ErrorPtr in_error) {
      if (error) {
        *error = std::move(in_error);
        return;
      }
      succeeded = true;
    };
    dev_reg_->RefreshAccessToken(base::Bind(callback));
    return succeeded;
  }

  void SetAccessToken() { dev_reg_->access_token_ = test_data::kAccessToken; }

  GcdState GetGcdState() const { return dev_reg_->GetGcdState(); }

  bool HaveRegistrationCredentials() const {
    return dev_reg_->HaveRegistrationCredentials();
  }

  provider::test::FakeTaskRunner task_runner_;
  provider::test::MockConfigStore config_store_;
  StrictMock<MockHttpClient> http_client_;
  base::DictionaryValue data_;
  Config* config_{nullptr};
  std::unique_ptr<DeviceRegistrationInfo> dev_reg_;
  std::shared_ptr<CommandManager> command_manager_;
  StrictMock<MockStateChangeQueueInterface> mock_state_change_queue_;
  std::shared_ptr<StateManager> state_manager_;
};

TEST_F(DeviceRegistrationInfoTest, GetServiceURL) {
  EXPECT_EQ(test_data::kServiceURL, dev_reg_->GetServiceURL());
  std::string url = test_data::kServiceURL;
  url += "registrationTickets";
  EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets"));
  url += "?key=";
  url += test_data::kApiKey;
  EXPECT_EQ(url, dev_reg_->GetServiceURL("registrationTickets",
                                         {{"key", test_data::kApiKey}}));
  url += "&restart=true";
  EXPECT_EQ(url, dev_reg_->GetServiceURL(
                     "registrationTickets",
                     {
                         {"key", test_data::kApiKey}, {"restart", "true"},
                     }));
}

TEST_F(DeviceRegistrationInfoTest, GetOAuthURL) {
  EXPECT_EQ(test_data::kOAuthURL, dev_reg_->GetOAuthURL());
  std::string url = test_data::kOAuthURL;
  url += "auth?redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&";
  url += "response_type=code&";
  url += "client_id=";
  url += test_data::kClientId;
  EXPECT_EQ(url, dev_reg_->GetOAuthURL(
                     "auth", {{"redirect_uri", "urn:ietf:wg:oauth:2.0:oob"},
                              {"response_type", "code"},
                              {"client_id", test_data::kClientId}}));
}

TEST_F(DeviceRegistrationInfoTest, HaveRegistrationCredentials) {
  EXPECT_FALSE(HaveRegistrationCredentials());
  ReloadSettings();

  EXPECT_CALL(
      http_client_,
      SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
                  HttpClient::Headers{GetFormHeader()}, _, _))
      .WillOnce(WithArgs<3, 4>(Invoke([](
          const std::string& data,
          const HttpClient::SendRequestCallback& callback) {
        EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
        EXPECT_EQ(test_data::kRefreshToken,
                  GetFormField(data, "refresh_token"));
        EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
        EXPECT_EQ(test_data::kClientSecret,
                  GetFormField(data, "client_secret"));

        base::DictionaryValue json;
        json.SetString("access_token", test_data::kAccessToken);
        json.SetInteger("expires_in", 3600);

        callback.Run(ReplyWithJson(200, json), nullptr);
      })));

  EXPECT_TRUE(RefreshAccessToken(nullptr));
  EXPECT_TRUE(HaveRegistrationCredentials());
}

TEST_F(DeviceRegistrationInfoTest, CheckAuthenticationFailure) {
  ReloadSettings();
  EXPECT_EQ(GcdState::kConnecting, GetGcdState());

  EXPECT_CALL(
      http_client_,
      SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
                  HttpClient::Headers{GetFormHeader()}, _, _))
      .WillOnce(WithArgs<3, 4>(Invoke([](
          const std::string& data,
          const HttpClient::SendRequestCallback& callback) {
        EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
        EXPECT_EQ(test_data::kRefreshToken,
                  GetFormField(data, "refresh_token"));
        EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
        EXPECT_EQ(test_data::kClientSecret,
                  GetFormField(data, "client_secret"));

        base::DictionaryValue json;
        json.SetString("error", "unable_to_authenticate");
        callback.Run(ReplyWithJson(400, json), nullptr);
      })));

  ErrorPtr error;
  EXPECT_FALSE(RefreshAccessToken(&error));
  EXPECT_TRUE(error->HasError(kErrorDomainOAuth2, "unable_to_authenticate"));
  EXPECT_EQ(GcdState::kConnecting, GetGcdState());
}

TEST_F(DeviceRegistrationInfoTest, CheckDeregistration) {
  ReloadSettings();
  EXPECT_EQ(GcdState::kConnecting, GetGcdState());

  EXPECT_CALL(
      http_client_,
      SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
                  HttpClient::Headers{GetFormHeader()}, _, _))
      .WillOnce(WithArgs<3, 4>(Invoke([](
          const std::string& data,
          const HttpClient::SendRequestCallback& callback) {
        EXPECT_EQ("refresh_token", GetFormField(data, "grant_type"));
        EXPECT_EQ(test_data::kRefreshToken,
                  GetFormField(data, "refresh_token"));
        EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
        EXPECT_EQ(test_data::kClientSecret,
                  GetFormField(data, "client_secret"));

        base::DictionaryValue json;
        json.SetString("error", "invalid_grant");
        callback.Run(ReplyWithJson(400, json), nullptr);
      })));

  ErrorPtr error;
  EXPECT_FALSE(RefreshAccessToken(&error));
  EXPECT_TRUE(error->HasError(kErrorDomainOAuth2, "invalid_grant"));
  EXPECT_EQ(test_data::kDeviceId, dev_reg_->GetSettings().cloud_id);
}

TEST_F(DeviceRegistrationInfoTest, GetDeviceInfo) {
  ReloadSettings();
  SetAccessToken();

  EXPECT_CALL(
      http_client_,
      SendRequest(HttpClient::Method::kGet, dev_reg_->GetDeviceURL(),
                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
      .WillOnce(WithArgs<3, 4>(
          Invoke([](const std::string& data,
                    const HttpClient::SendRequestCallback& callback) {
            base::DictionaryValue json;
            json.SetString("channel.supportedType", "xmpp");
            json.SetString("deviceKind", "vendor");
            json.SetString("id", test_data::kDeviceId);
            json.SetString("kind", "weave#device");
            callback.Run(ReplyWithJson(200, json), nullptr);
          })));

  bool succeeded = false;
  auto callback = [&succeeded](const base::DictionaryValue& info,
                               ErrorPtr error) {
    EXPECT_FALSE(error);
    std::string id;
    EXPECT_TRUE(info.GetString("id", &id));
    EXPECT_EQ(test_data::kDeviceId, id);
    succeeded = true;
  };
  dev_reg_->GetDeviceInfo(base::Bind(callback));
  EXPECT_TRUE(succeeded);
}

TEST_F(DeviceRegistrationInfoTest, RegisterDevice) {
  auto json_cmds = CreateDictionaryValue(R"({
    'base': {
      'reboot': {
        'parameters': {'delay': {'minimum': 10}},
        'minimalRole': 'user',
        'results': {}
      }
    },
    'robot': {
      '_jump': {
        'parameters': {'_height': 'integer'},
        'minimalRole': 'user',
        'results': {}
      }
    }
  })");
  EXPECT_TRUE(command_manager_->LoadCommands(*json_cmds, nullptr));

  std::string ticket_url = dev_reg_->GetServiceURL("registrationTickets/") +
                           test_data::kClaimTicketId;
  EXPECT_CALL(http_client_,
              SendRequest(HttpClient::Method::kPatch,
                          ticket_url + "?key=" + test_data::kApiKey,
                          HttpClient::Headers{GetJsonHeader()}, _, _))
      .WillOnce(WithArgs<3, 4>(Invoke([](
          const std::string& data,
          const HttpClient::SendRequestCallback& callback) {
        auto json = test::CreateDictionaryValue(data);
        EXPECT_NE(nullptr, json.get());
        std::string value;
        EXPECT_TRUE(json->GetString("id", &value));
        EXPECT_EQ(test_data::kClaimTicketId, value);
        EXPECT_TRUE(
            json->GetString("deviceDraft.channel.supportedType", &value));
        EXPECT_EQ("pull", value);
        EXPECT_TRUE(json->GetString("oauthClientId", &value));
        EXPECT_EQ(test_data::kClientId, value);
        EXPECT_TRUE(json->GetString("deviceDraft.description", &value));
        EXPECT_EQ("Easy to clean", value);
        EXPECT_TRUE(json->GetString("deviceDraft.location", &value));
        EXPECT_EQ("Kitchen", value);
        EXPECT_TRUE(json->GetString("deviceDraft.modelManifestId", &value));
        EXPECT_EQ("AAAAA", value);
        EXPECT_TRUE(json->GetString("deviceDraft.name", &value));
        EXPECT_EQ("Coffee Pot", value);
        base::DictionaryValue* commandDefs = nullptr;
        EXPECT_TRUE(
            json->GetDictionary("deviceDraft.commandDefs", &commandDefs));
        EXPECT_FALSE(commandDefs->empty());

        auto expected = R"({
            'base': {
              'reboot': {
                'parameters': {
                  'delay': {
                    'minimum': 10,
                    'type': 'integer'
                  }
                },
                'minimalRole': 'user'
              }
            },
            'robot': {
              '_jump': {
                'parameters': {
                  '_height': {
                    'type': 'integer'
                  }
                },
                'minimalRole': 'user'
              }
            }
          })";
        EXPECT_JSON_EQ(expected, *commandDefs);

        base::DictionaryValue json_resp;
        json_resp.SetString("id", test_data::kClaimTicketId);
        json_resp.SetString("kind", "weave#registrationTicket");
        json_resp.SetString("oauthClientId", test_data::kClientId);
        base::DictionaryValue* device_draft = nullptr;
        EXPECT_TRUE(json->GetDictionary("deviceDraft", &device_draft));
        auto device_draft_copy = device_draft->CreateDeepCopy();
        device_draft_copy->SetString("id", test_data::kDeviceId);
        device_draft_copy->SetString("kind", "weave#device");
        json_resp.Set("deviceDraft", std::move(device_draft_copy));

        callback.Run(ReplyWithJson(200, json_resp), nullptr);
      })));

  EXPECT_CALL(http_client_,
              SendRequest(HttpClient::Method::kPost,
                          ticket_url + "/finalize?key=" + test_data::kApiKey,
                          HttpClient::Headers{}, _, _))
      .WillOnce(WithArgs<4>(
          Invoke([](const HttpClient::SendRequestCallback& callback) {
            base::DictionaryValue json;
            json.SetString("id", test_data::kClaimTicketId);
            json.SetString("kind", "weave#registrationTicket");
            json.SetString("oauthClientId", test_data::kClientId);
            json.SetString("userEmail", "user@email.com");
            json.SetString("deviceDraft.id", test_data::kDeviceId);
            json.SetString("deviceDraft.kind", "weave#device");
            json.SetString("deviceDraft.channel.supportedType", "xmpp");
            json.SetString("robotAccountEmail", test_data::kRobotAccountEmail);
            json.SetString("robotAccountAuthorizationCode",
                           test_data::kRobotAccountAuthCode);
            callback.Run(ReplyWithJson(200, json), nullptr);
          })));

  EXPECT_CALL(
      http_client_,
      SendRequest(HttpClient::Method::kPost, dev_reg_->GetOAuthURL("token"),
                  HttpClient::Headers{GetFormHeader()}, _, _))
      .WillOnce(WithArgs<3, 4>(Invoke([](
          const std::string& data,
          const HttpClient::SendRequestCallback& callback) {
        EXPECT_EQ("authorization_code", GetFormField(data, "grant_type"));
        EXPECT_EQ(test_data::kRobotAccountAuthCode, GetFormField(data, "code"));
        EXPECT_EQ(test_data::kClientId, GetFormField(data, "client_id"));
        EXPECT_EQ(test_data::kClientSecret,
                  GetFormField(data, "client_secret"));
        EXPECT_EQ("oob", GetFormField(data, "redirect_uri"));

        base::DictionaryValue json;
        json.SetString("access_token", test_data::kAccessToken);
        json.SetString("token_type", "Bearer");
        json.SetString("refresh_token", test_data::kRefreshToken);
        json.SetInteger("expires_in", 3600);

        callback.Run(ReplyWithJson(200, json), nullptr);
      })));

  bool done = false;
  dev_reg_->RegisterDevice(
      test_data::kClaimTicketId, base::Bind([this, &done](ErrorPtr error) {
        EXPECT_FALSE(error);
        done = true;
        task_runner_.Break();
        EXPECT_EQ(GcdState::kConnecting, GetGcdState());

        // Validate the device info saved to storage...
        EXPECT_EQ(test_data::kDeviceId, dev_reg_->GetSettings().cloud_id);
        EXPECT_EQ(test_data::kRefreshToken,
                  dev_reg_->GetSettings().refresh_token);
        EXPECT_EQ(test_data::kRobotAccountEmail,
                  dev_reg_->GetSettings().robot_account);
      }));
  task_runner_.Run();
  EXPECT_TRUE(done);
}

TEST_F(DeviceRegistrationInfoTest, OOBRegistrationStatus) {
  // After we've been initialized, we should be either offline or
  // unregistered, depending on whether or not we've found credentials.
  EXPECT_EQ(GcdState::kUnconfigured, GetGcdState());
  // Put some credentials into our state, make sure we call that offline.
  ReloadSettings();
  EXPECT_EQ(GcdState::kConnecting, GetGcdState());
}

class DeviceRegistrationInfoUpdateCommandTest
    : public DeviceRegistrationInfoTest {
 protected:
  void SetUp() override {
    DeviceRegistrationInfoTest::SetUp();

    ReloadSettings();
    SetAccessToken();

    auto json_cmds = CreateDictionaryValue(R"({
      'robot': {
        '_jump': {
          'parameters': {'_height': 'integer'},
          'progress': {'progress': 'integer'},
          'results': {'status': 'string'},
          'minimalRole': 'user'
        }
      }
    })");
    EXPECT_TRUE(command_manager_->LoadCommands(*json_cmds, nullptr));

    command_url_ = dev_reg_->GetServiceURL("commands/1234");

    auto commands_json = CreateValue(R"([{
      'name':'robot._jump',
      'id':'1234',
      'parameters': {'_height': 100},
      'minimalRole': 'user'
    }])");
    ASSERT_NE(nullptr, commands_json.get());
    const base::ListValue* command_list = nullptr;
    ASSERT_TRUE(commands_json->GetAsList(&command_list));
    PublishCommands(*command_list);
    command_ = command_manager_->FindCommand("1234");
    ASSERT_NE(nullptr, command_);
  }

  void TearDown() override {
    task_runner_.RunOnce();
    DeviceRegistrationInfoTest::TearDown();
  }

  Command* command_{nullptr};
  std::string command_url_;
};

TEST_F(DeviceRegistrationInfoUpdateCommandTest, SetProgress) {
  EXPECT_CALL(
      http_client_,
      SendRequest(HttpClient::Method::kPatch, command_url_,
                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
      .WillOnce(WithArgs<3, 4>(Invoke([](
          const std::string& data,
          const HttpClient::SendRequestCallback& callback) {
        EXPECT_JSON_EQ((R"({"state":"inProgress","progress":{"progress":18}})"),
                       *CreateDictionaryValue(data));
        base::DictionaryValue json;
        callback.Run(ReplyWithJson(200, json), nullptr);
      })));
  EXPECT_TRUE(command_->SetProgress(*CreateDictionaryValue("{'progress':18}"),
                                    nullptr));
}

TEST_F(DeviceRegistrationInfoUpdateCommandTest, Complete) {
  EXPECT_CALL(
      http_client_,
      SendRequest(HttpClient::Method::kPatch, command_url_,
                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
      .WillOnce(WithArgs<3, 4>(
          Invoke([](const std::string& data,
                    const HttpClient::SendRequestCallback& callback) {
            EXPECT_JSON_EQ(R"({"state":"done", "results":{"status":"Ok"}})",
                           *CreateDictionaryValue(data));
            base::DictionaryValue json;
            callback.Run(ReplyWithJson(200, json), nullptr);
          })));
  EXPECT_TRUE(
      command_->Complete(*CreateDictionaryValue("{'status': 'Ok'}"), nullptr));
}

TEST_F(DeviceRegistrationInfoUpdateCommandTest, Cancel) {
  EXPECT_CALL(
      http_client_,
      SendRequest(HttpClient::Method::kPatch, command_url_,
                  HttpClient::Headers{GetAuthHeader(), GetJsonHeader()}, _, _))
      .WillOnce(WithArgs<3, 4>(Invoke([](
          const std::string& data,
          const HttpClient::SendRequestCallback& callback) {
        EXPECT_JSON_EQ(R"({"state":"cancelled"})",
                       *CreateDictionaryValue(data));
        base::DictionaryValue json;
        callback.Run(ReplyWithJson(200, json), nullptr);
      })));
  EXPECT_TRUE(command_->Cancel(nullptr));
}

}  // namespace weave
