// 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/config.h"

#include <set>

#include <base/bind.h>
#include <base/guid.h>
#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/values.h>
#include <weave/enum_to_string.h>

#include "src/privet/privet_types.h"
#include "src/string_utils.h"

namespace weave {

namespace config_keys {

const char kVersion[] = "version";

const char kClientId[] = "client_id";
const char kClientSecret[] = "client_secret";
const char kApiKey[] = "api_key";
const char kOAuthURL[] = "oauth_url";
const char kServiceURL[] = "service_url";
const char kName[] = "name";
const char kDescription[] = "description";
const char kLocation[] = "location";
const char kLocalAnonymousAccessRole[] = "local_anonymous_access_role";
const char kLocalDiscoveryEnabled[] = "local_discovery_enabled";
const char kLocalPairingEnabled[] = "local_pairing_enabled";
const char kRefreshToken[] = "refresh_token";
const char kCloudId[] = "cloud_id";
const char kDeviceId[] = "device_id";
const char kRobotAccount[] = "robot_account";
const char kLastConfiguredSsid[] = "last_configured_ssid";
const char kSecret[] = "secret";

}  // namespace config_keys

namespace {

const int kCurrentConfigVersion = 1;

void MigrateFromV0(base::DictionaryValue* dict) {
  std::string cloud_id;
  if (dict->GetString(config_keys::kCloudId, &cloud_id) && !cloud_id.empty())
    return;
  scoped_ptr<base::Value> tmp;
  if (dict->Remove(config_keys::kDeviceId, &tmp))
    dict->Set(config_keys::kCloudId, std::move(tmp));
}

Config::Settings CreateDefaultSettings() {
  Config::Settings result;
  result.oauth_url = "https://accounts.google.com/o/oauth2/";
  result.service_url = "https://www.googleapis.com/clouddevices/v1/";
  result.local_anonymous_access_role = AuthScope::kViewer;
  result.pairing_modes.emplace(PairingType::kPinCode);
  result.device_id = base::GenerateGUID();
  return result;
}

}  // namespace

Config::Config(provider::ConfigStore* config_store)
    : settings_{CreateDefaultSettings()}, config_store_{config_store} {
}

void Config::AddOnChangedCallback(const OnChangedCallback& callback) {
  on_changed_.push_back(callback);
  // Force to read current state.
  callback.Run(settings_);
}

const Config::Settings& Config::GetSettings() const {
  return settings_;
}

void Config::Load() {
  Transaction change{this};
  change.save_ = false;

  settings_ = CreateDefaultSettings();

  if (!config_store_)
    return;

  // Crash on any mistakes in defaults.
  CHECK(config_store_->LoadDefaults(&settings_));

  CHECK(!settings_.client_id.empty());
  CHECK(!settings_.client_secret.empty());
  CHECK(!settings_.api_key.empty());
  CHECK(!settings_.oauth_url.empty());
  CHECK(!settings_.service_url.empty());
  CHECK(!settings_.oem_name.empty());
  CHECK(!settings_.model_name.empty());
  CHECK(!settings_.model_id.empty());
  CHECK(!settings_.name.empty());
  CHECK(!settings_.device_id.empty());
  CHECK_EQ(
      settings_.embedded_code.empty(),
      std::find(settings_.pairing_modes.begin(), settings_.pairing_modes.end(),
                PairingType::kEmbeddedCode) == settings_.pairing_modes.end());

  // Values below will be generated at runtime.
  CHECK(settings_.cloud_id.empty());
  CHECK(settings_.refresh_token.empty());
  CHECK(settings_.robot_account.empty());
  CHECK(settings_.last_configured_ssid.empty());
  CHECK(settings_.secret.empty());

  change.LoadState();
}

void Config::Transaction::LoadState() {
  if (!config_->config_store_)
    return;
  std::string json_string = config_->config_store_->LoadSettings();
  if (json_string.empty())
    return;

  auto value = base::JSONReader::Read(json_string);
  base::DictionaryValue* dict = nullptr;
  if (!value || !value->GetAsDictionary(&dict)) {
    LOG(ERROR) << "Failed to parse settings.";
    return;
  }

  int loaded_version = 0;
  dict->GetInteger(config_keys::kVersion, &loaded_version);

  if (loaded_version != kCurrentConfigVersion) {
    LOG(INFO) << "State version mismatch. expected: " << kCurrentConfigVersion
              << ", loaded: " << loaded_version;
    save_ = true;
  }

  if (loaded_version == 0) {
    MigrateFromV0(dict);
  }

  std::string tmp;
  bool tmp_bool{false};

  if (dict->GetString(config_keys::kClientId, &tmp))
    set_client_id(tmp);

  if (dict->GetString(config_keys::kClientSecret, &tmp))
    set_client_secret(tmp);

  if (dict->GetString(config_keys::kApiKey, &tmp))
    set_api_key(tmp);

  if (dict->GetString(config_keys::kOAuthURL, &tmp))
    set_oauth_url(tmp);

  if (dict->GetString(config_keys::kServiceURL, &tmp))
    set_service_url(tmp);

  if (dict->GetString(config_keys::kName, &tmp))
    set_name(tmp);

  if (dict->GetString(config_keys::kDescription, &tmp))
    set_description(tmp);

  if (dict->GetString(config_keys::kLocation, &tmp))
    set_location(tmp);

  AuthScope scope{AuthScope::kNone};
  if (dict->GetString(config_keys::kLocalAnonymousAccessRole, &tmp) &&
      StringToEnum(tmp, &scope)) {
    set_local_anonymous_access_role(scope);
  }

  if (dict->GetBoolean(config_keys::kLocalDiscoveryEnabled, &tmp_bool))
    set_local_discovery_enabled(tmp_bool);

  if (dict->GetBoolean(config_keys::kLocalPairingEnabled, &tmp_bool))
    set_local_pairing_enabled(tmp_bool);

  if (dict->GetString(config_keys::kCloudId, &tmp))
    set_cloud_id(tmp);

  if (dict->GetString(config_keys::kDeviceId, &tmp))
    set_device_id(tmp);

  if (dict->GetString(config_keys::kRefreshToken, &tmp))
    set_refresh_token(tmp);

  if (dict->GetString(config_keys::kRobotAccount, &tmp))
    set_robot_account(tmp);

  if (dict->GetString(config_keys::kLastConfiguredSsid, &tmp))
    set_last_configured_ssid(tmp);

  if (dict->GetString(config_keys::kSecret, &tmp))
    set_secret(tmp);
}

void Config::Save() {
  if (!config_store_)
    return;

  base::DictionaryValue dict;
  dict.SetInteger(config_keys::kVersion, kCurrentConfigVersion);

  dict.SetString(config_keys::kClientId, settings_.client_id);
  dict.SetString(config_keys::kClientSecret, settings_.client_secret);
  dict.SetString(config_keys::kApiKey, settings_.api_key);
  dict.SetString(config_keys::kOAuthURL, settings_.oauth_url);
  dict.SetString(config_keys::kServiceURL, settings_.service_url);
  dict.SetString(config_keys::kRefreshToken, settings_.refresh_token);
  dict.SetString(config_keys::kCloudId, settings_.cloud_id);
  dict.SetString(config_keys::kDeviceId, settings_.device_id);
  dict.SetString(config_keys::kRobotAccount, settings_.robot_account);
  dict.SetString(config_keys::kLastConfiguredSsid,
                 settings_.last_configured_ssid);
  dict.SetString(config_keys::kSecret, settings_.secret);
  dict.SetString(config_keys::kName, settings_.name);
  dict.SetString(config_keys::kDescription, settings_.description);
  dict.SetString(config_keys::kLocation, settings_.location);
  dict.SetString(config_keys::kLocalAnonymousAccessRole,
                 EnumToString(settings_.local_anonymous_access_role));
  dict.SetBoolean(config_keys::kLocalDiscoveryEnabled,
                  settings_.local_discovery_enabled);
  dict.SetBoolean(config_keys::kLocalPairingEnabled,
                  settings_.local_pairing_enabled);

  std::string json_string;
  base::JSONWriter::WriteWithOptions(
      dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string);

  config_store_->SaveSettings(json_string);
}

Config::Transaction::~Transaction() {
  Commit();
}

void Config::Transaction::Commit() {
  if (!config_)
    return;
  if (save_)
    config_->Save();
  for (const auto& cb : config_->on_changed_)
    cb.Run(*settings_);
  config_ = nullptr;
}

}  // namespace weave
