// 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 "chrome/browser/supervised_user/supervised_user_sync_service.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "sync/api/sync_change.h"
#include "sync/api/sync_data.h"
#include "sync/api/sync_error.h"
#include "sync/api/sync_error_factory.h"
#include "sync/api/sync_merge_result.h"
#include "sync/protocol/sync.pb.h"

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/users/avatar/default_user_images.h"
#endif

using base::DictionaryValue;
using user_prefs::PrefRegistrySyncable;
using syncer::SUPERVISED_USERS;
using syncer::ModelType;
using syncer::SyncChange;
using syncer::SyncChangeList;
using syncer::SyncChangeProcessor;
using syncer::SyncData;
using syncer::SyncDataList;
using syncer::SyncError;
using syncer::SyncErrorFactory;
using syncer::SyncMergeResult;
using sync_pb::ManagedUserSpecifics;

namespace {

#if defined(OS_CHROMEOS)
const char kChromeOSAvatarPrefix[] = "chromeos-avatar-index:";
#else
const char kChromeAvatarPrefix[] = "chrome-avatar-index:";
#endif

SyncData CreateLocalSyncData(const std::string& id,
                             const std::string& name,
                             bool acknowledged,
                             const std::string& master_key,
                             const std::string& chrome_avatar,
                             const std::string& chromeos_avatar,
                             const std::string& password_signature_key,
                             const std::string& password_encryption_key) {
  ::sync_pb::EntitySpecifics specifics;
  specifics.mutable_managed_user()->set_id(id);
  specifics.mutable_managed_user()->set_name(name);
  if (!chrome_avatar.empty())
    specifics.mutable_managed_user()->set_chrome_avatar(chrome_avatar);
  if (!chromeos_avatar.empty())
    specifics.mutable_managed_user()->set_chromeos_avatar(chromeos_avatar);
  if (!master_key.empty())
    specifics.mutable_managed_user()->set_master_key(master_key);
  if (acknowledged)
    specifics.mutable_managed_user()->set_acknowledged(true);
  if (!password_signature_key.empty()) {
    specifics.mutable_managed_user()->
        set_password_signature_key(password_signature_key);
  }
  if (!password_encryption_key.empty()) {
    specifics.mutable_managed_user()->
        set_password_encryption_key(password_encryption_key);
  }
  return SyncData::CreateLocalData(id, name, specifics);
}

SyncData CreateSyncDataFromDictionaryEntry(const std::string& id,
                                           const base::Value& value) {
  const base::DictionaryValue* dict = NULL;
  bool success = value.GetAsDictionary(&dict);
  DCHECK(success);
  bool acknowledged = false;
  dict->GetBoolean(SupervisedUserSyncService::kAcknowledged, &acknowledged);
  std::string name;
  dict->GetString(SupervisedUserSyncService::kName, &name);
  DCHECK(!name.empty());
  std::string master_key;
  dict->GetString(SupervisedUserSyncService::kMasterKey, &master_key);
  std::string chrome_avatar;
  dict->GetString(SupervisedUserSyncService::kChromeAvatar, &chrome_avatar);
  std::string chromeos_avatar;
  dict->GetString(SupervisedUserSyncService::kChromeOsAvatar, &chromeos_avatar);
  std::string signature;
  dict->GetString(SupervisedUserSyncService::kPasswordSignatureKey, &signature);
  std::string encryption;
  dict->GetString(SupervisedUserSyncService::kPasswordEncryptionKey,
                  &encryption);

  return CreateLocalSyncData(id,
                             name,
                             acknowledged,
                             master_key,
                             chrome_avatar,
                             chromeos_avatar,
                             signature,
                             encryption);
}

}  // namespace

const char SupervisedUserSyncService::kAcknowledged[] = "acknowledged";
const char SupervisedUserSyncService::kChromeAvatar[] = "chromeAvatar";
const char SupervisedUserSyncService::kChromeOsAvatar[] = "chromeOsAvatar";
const char SupervisedUserSyncService::kMasterKey[] = "masterKey";
const char SupervisedUserSyncService::kName[] = "name";
const char SupervisedUserSyncService::kPasswordSignatureKey[] =
    "passwordSignatureKey";
const char SupervisedUserSyncService::kPasswordEncryptionKey[] =
    "passwordEncryptionKey";
const int SupervisedUserSyncService::kNoAvatar = -100;

SupervisedUserSyncService::SupervisedUserSyncService(PrefService* prefs)
    : prefs_(prefs) {
  pref_change_registrar_.Init(prefs_);
  pref_change_registrar_.Add(
      prefs::kGoogleServicesLastUsername,
      base::Bind(&SupervisedUserSyncService::OnLastSignedInUsernameChange,
                 base::Unretained(this)));
}

SupervisedUserSyncService::~SupervisedUserSyncService() {
}

// static
void SupervisedUserSyncService::RegisterProfilePrefs(
    PrefRegistrySyncable* registry) {
  registry->RegisterDictionaryPref(prefs::kSupervisedUsers,
                                   PrefRegistrySyncable::UNSYNCABLE_PREF);
}

// static
bool SupervisedUserSyncService::GetAvatarIndex(const std::string& avatar_str,
                                               int* avatar_index) {
  DCHECK(avatar_index);
  if (avatar_str.empty()) {
    *avatar_index = kNoAvatar;
    return true;
  }
#if defined(OS_CHROMEOS)
  const char* prefix = kChromeOSAvatarPrefix;
#else
  const char* prefix = kChromeAvatarPrefix;
#endif
  size_t prefix_len = strlen(prefix);
  if (avatar_str.size() <= prefix_len ||
      avatar_str.substr(0, prefix_len) != prefix) {
    return false;
  }

  if (!base::StringToInt(avatar_str.substr(prefix_len), avatar_index))
    return false;

  const int kChromeOSDummyAvatarIndex = -111;

#if defined(OS_CHROMEOS)
  return (*avatar_index == kChromeOSDummyAvatarIndex ||
          (*avatar_index >= chromeos::kFirstDefaultImageIndex &&
           *avatar_index < chromeos::kDefaultImagesCount));
#else
  // Check if the Chrome avatar index is set to a dummy value. Some early
  // supervised user profiles on ChromeOS stored a dummy avatar index as a
  // Chrome Avatar before there was logic to sync the ChromeOS avatar
  // separately. Handle this as if the Chrome Avatar was not chosen yet (which
  // is correct for these profiles).
  if (*avatar_index == kChromeOSDummyAvatarIndex)
    *avatar_index = kNoAvatar;
  return (*avatar_index == kNoAvatar ||
          (*avatar_index >= 0 &&
           static_cast<size_t>(*avatar_index) <
               profiles::GetDefaultAvatarIconCount()));
#endif
}

// static
std::string SupervisedUserSyncService::BuildAvatarString(int avatar_index) {
#if defined(OS_CHROMEOS)
  const char* prefix = kChromeOSAvatarPrefix;
#else
  const char* prefix = kChromeAvatarPrefix;
#endif
  return base::StringPrintf("%s%d", prefix, avatar_index);
}

void SupervisedUserSyncService::AddObserver(
    SupervisedUserSyncServiceObserver* observer) {
  observers_.AddObserver(observer);
}

void SupervisedUserSyncService::RemoveObserver(
    SupervisedUserSyncServiceObserver* observer) {
  observers_.RemoveObserver(observer);
}

scoped_ptr<base::DictionaryValue> SupervisedUserSyncService::CreateDictionary(
    const std::string& name,
    const std::string& master_key,
    const std::string& signature_key,
    const std::string& encryption_key,
    int avatar_index) {
  scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
  result->SetString(kName, name);
  result->SetString(kMasterKey, master_key);
  result->SetString(kPasswordSignatureKey, signature_key);
  result->SetString(kPasswordEncryptionKey, encryption_key);
  // TODO(akuegel): Get rid of the avatar stuff here when Chrome OS switches
  // to the avatar index that is stored as a shared setting.
  std::string chrome_avatar;
  std::string chromeos_avatar;
#if defined(OS_CHROMEOS)
  chromeos_avatar = BuildAvatarString(avatar_index);
#else
  chrome_avatar = BuildAvatarString(avatar_index);
#endif
  result->SetString(kChromeAvatar, chrome_avatar);
  result->SetString(kChromeOsAvatar, chromeos_avatar);
  return result.Pass();
}

void SupervisedUserSyncService::AddSupervisedUser(
    const std::string& id,
    const std::string& name,
    const std::string& master_key,
    const std::string& signature_key,
    const std::string& encryption_key,
    int avatar_index) {
  UpdateSupervisedUserImpl(id,
                           name,
                           master_key,
                           signature_key,
                           encryption_key,
                           avatar_index,
                           true /* add */);
}

void SupervisedUserSyncService::UpdateSupervisedUser(
    const std::string& id,
    const std::string& name,
    const std::string& master_key,
    const std::string& signature_key,
    const std::string& encryption_key,
    int avatar_index) {
  UpdateSupervisedUserImpl(id,
                           name,
                           master_key,
                           signature_key,
                           encryption_key,
                           avatar_index,
                           false /* update */);
}

void SupervisedUserSyncService::UpdateSupervisedUserImpl(
    const std::string& id,
    const std::string& name,
    const std::string& master_key,
    const std::string& signature_key,
    const std::string& encryption_key,
    int avatar_index,
    bool add_user) {
  DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
  base::DictionaryValue* dict = update.Get();
  scoped_ptr<base::DictionaryValue> value = CreateDictionary(
      name, master_key, signature_key, encryption_key, avatar_index);

  DCHECK_EQ(add_user, !dict->HasKey(id));
  base::DictionaryValue* entry = value.get();
  dict->SetWithoutPathExpansion(id, value.release());

  if (!sync_processor_)
    return;

  // If we're already syncing, create a new change and upload it.
  SyncChangeList change_list;
  change_list.push_back(
      SyncChange(FROM_HERE,
                 add_user ? SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE,
                 CreateSyncDataFromDictionaryEntry(id, *entry)));
  SyncError error =
      sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
  DCHECK(!error.IsSet()) << error.ToString();
}

void SupervisedUserSyncService::DeleteSupervisedUser(const std::string& id) {
  DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
  bool success = update->RemoveWithoutPathExpansion(id, NULL);
  DCHECK(success);

  if (!sync_processor_)
    return;

  SyncChangeList change_list;
  change_list.push_back(SyncChange(
      FROM_HERE,
      SyncChange::ACTION_DELETE,
      SyncData::CreateLocalDelete(id, SUPERVISED_USERS)));
  SyncError sync_error =
      sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
  DCHECK(!sync_error.IsSet());
}

const base::DictionaryValue* SupervisedUserSyncService::GetSupervisedUsers() {
  DCHECK(sync_processor_);
  return prefs_->GetDictionary(prefs::kSupervisedUsers);
}

bool SupervisedUserSyncService::UpdateSupervisedUserAvatarIfNeeded(
    const std::string& id,
    int avatar_index) {
  DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
  base::DictionaryValue* dict = update.Get();
  DCHECK(dict->HasKey(id));
  base::DictionaryValue* value = NULL;
  bool success = dict->GetDictionaryWithoutPathExpansion(id, &value);
  DCHECK(success);

  bool acknowledged = false;
  value->GetBoolean(SupervisedUserSyncService::kAcknowledged, &acknowledged);
  std::string name;
  value->GetString(SupervisedUserSyncService::kName, &name);
  std::string master_key;
  value->GetString(SupervisedUserSyncService::kMasterKey, &master_key);
  std::string signature;
  value->GetString(SupervisedUserSyncService::kPasswordSignatureKey,
                   &signature);
  std::string encryption;
  value->GetString(SupervisedUserSyncService::kPasswordEncryptionKey,
                   &encryption);
  std::string chromeos_avatar;
  value->GetString(SupervisedUserSyncService::kChromeOsAvatar,
                   &chromeos_avatar);
  std::string chrome_avatar;
  value->GetString(SupervisedUserSyncService::kChromeAvatar, &chrome_avatar);
  // The following check is just for safety. We want to avoid that the existing
  // avatar selection is overwritten. Currently we don't allow the user to
  // choose a different avatar in the recreation dialog, anyway, if there is
  // already an avatar selected.
#if defined(OS_CHROMEOS)
  if (!chromeos_avatar.empty() && avatar_index != kNoAvatar)
    return false;
#else
  if (!chrome_avatar.empty() && avatar_index != kNoAvatar)
    return false;
#endif

  chrome_avatar = avatar_index == kNoAvatar ?
      std::string() : BuildAvatarString(avatar_index);
#if defined(OS_CHROMEOS)
  value->SetString(kChromeOsAvatar, chrome_avatar);
#else
  value->SetString(kChromeAvatar, chrome_avatar);
#endif

  if (!sync_processor_)
    return true;

  SyncChangeList change_list;
  change_list.push_back(SyncChange(
      FROM_HERE,
      SyncChange::ACTION_UPDATE,
      CreateLocalSyncData(id, name, acknowledged, master_key,
                          chrome_avatar, chromeos_avatar,
                          signature, encryption)));
  SyncError error =
      sync_processor_->ProcessSyncChanges(FROM_HERE, change_list);
  DCHECK(!error.IsSet()) << error.ToString();
  return true;
}

void SupervisedUserSyncService::ClearSupervisedUserAvatar(
    const std::string& id) {
  bool cleared = UpdateSupervisedUserAvatarIfNeeded(id, kNoAvatar);
  DCHECK(cleared);
}

void SupervisedUserSyncService::GetSupervisedUsersAsync(
    const SupervisedUsersCallback& callback) {
  // If we are already syncing, just run the callback.
  if (sync_processor_) {
    callback.Run(GetSupervisedUsers());
    return;
  }

  // Otherwise queue it up until we start syncing.
  callbacks_.push_back(callback);
}

void SupervisedUserSyncService::Shutdown() {
  NotifySupervisedUsersSyncingStopped();
}

SyncMergeResult SupervisedUserSyncService::MergeDataAndStartSyncing(
    ModelType type,
    const SyncDataList& initial_sync_data,
    scoped_ptr<SyncChangeProcessor> sync_processor,
    scoped_ptr<SyncErrorFactory> error_handler) {
  DCHECK_EQ(SUPERVISED_USERS, type);
  sync_processor_ = sync_processor.Pass();
  error_handler_ = error_handler.Pass();

  SyncChangeList change_list;
  SyncMergeResult result(SUPERVISED_USERS);

  DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
  base::DictionaryValue* dict = update.Get();
  result.set_num_items_before_association(dict->size());
  std::set<std::string> seen_ids;
  int num_items_added = 0;
  int num_items_modified = 0;
  for (SyncDataList::const_iterator it = initial_sync_data.begin();
       it != initial_sync_data.end(); ++it) {
    DCHECK_EQ(SUPERVISED_USERS, it->GetDataType());
    const ManagedUserSpecifics& supervised_user =
        it->GetSpecifics().managed_user();
    base::DictionaryValue* value = new base::DictionaryValue();
    value->SetString(kName, supervised_user.name());
    value->SetBoolean(kAcknowledged, supervised_user.acknowledged());
    value->SetString(kMasterKey, supervised_user.master_key());
    value->SetString(kChromeAvatar, supervised_user.chrome_avatar());
    value->SetString(kChromeOsAvatar, supervised_user.chromeos_avatar());
    value->SetString(kPasswordSignatureKey,
                     supervised_user.password_signature_key());
    value->SetString(kPasswordEncryptionKey,
                     supervised_user.password_encryption_key());
    if (dict->HasKey(supervised_user.id()))
      num_items_modified++;
    else
      num_items_added++;
    dict->SetWithoutPathExpansion(supervised_user.id(), value);
    seen_ids.insert(supervised_user.id());
  }

  for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
    if (seen_ids.find(it.key()) != seen_ids.end())
      continue;

    change_list.push_back(
        SyncChange(FROM_HERE,
                   SyncChange::ACTION_ADD,
                   CreateSyncDataFromDictionaryEntry(it.key(), it.value())));
  }
  result.set_error(sync_processor_->ProcessSyncChanges(FROM_HERE, change_list));

  result.set_num_items_modified(num_items_modified);
  result.set_num_items_added(num_items_added);
  result.set_num_items_after_association(dict->size());

  DispatchCallbacks();

  return result;
}

void SupervisedUserSyncService::StopSyncing(ModelType type) {
  DCHECK_EQ(SUPERVISED_USERS, type);
  // The observers may want to change the Sync data, so notify them before
  // resetting the |sync_processor_|.
  NotifySupervisedUsersSyncingStopped();
  sync_processor_.reset();
  error_handler_.reset();
}

SyncDataList SupervisedUserSyncService::GetAllSyncData(
    ModelType type) const {
  SyncDataList data;
  DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
  base::DictionaryValue* dict = update.Get();
  for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance())
    data.push_back(CreateSyncDataFromDictionaryEntry(it.key(), it.value()));

  return data;
}

SyncError SupervisedUserSyncService::ProcessSyncChanges(
    const tracked_objects::Location& from_here,
    const SyncChangeList& change_list) {
  SyncError error;
  DictionaryPrefUpdate update(prefs_, prefs::kSupervisedUsers);
  base::DictionaryValue* dict = update.Get();
  for (SyncChangeList::const_iterator it = change_list.begin();
       it != change_list.end(); ++it) {
    SyncData data = it->sync_data();
    DCHECK_EQ(SUPERVISED_USERS, data.GetDataType());
    const ManagedUserSpecifics& supervised_user =
        data.GetSpecifics().managed_user();
    switch (it->change_type()) {
      case SyncChange::ACTION_ADD:
      case SyncChange::ACTION_UPDATE: {
        // Every item we get from the server should be acknowledged.
        DCHECK(supervised_user.acknowledged());
        const base::DictionaryValue* old_value = NULL;
        dict->GetDictionaryWithoutPathExpansion(supervised_user.id(),
                                                &old_value);

        // For an update action, the supervised user should already exist, for
        // an add action, it should not.
        DCHECK_EQ(
            old_value ? SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD,
            it->change_type());

        // If the supervised user switched from unacknowledged to acknowledged,
        // we might need to continue with a registration.
        if (old_value && !old_value->HasKey(kAcknowledged))
          NotifySupervisedUserAcknowledged(supervised_user.id());

        base::DictionaryValue* value = new base::DictionaryValue;
        value->SetString(kName, supervised_user.name());
        value->SetBoolean(kAcknowledged, supervised_user.acknowledged());
        value->SetString(kMasterKey, supervised_user.master_key());
        value->SetString(kChromeAvatar, supervised_user.chrome_avatar());
        value->SetString(kChromeOsAvatar, supervised_user.chromeos_avatar());
        value->SetString(kPasswordSignatureKey,
                         supervised_user.password_signature_key());
        value->SetString(kPasswordEncryptionKey,
                         supervised_user.password_encryption_key());
        dict->SetWithoutPathExpansion(supervised_user.id(), value);

        NotifySupervisedUsersChanged();
        break;
      }
      case SyncChange::ACTION_DELETE: {
        DCHECK(dict->HasKey(supervised_user.id())) << supervised_user.id();
        dict->RemoveWithoutPathExpansion(supervised_user.id(), NULL);
        break;
      }
      case SyncChange::ACTION_INVALID: {
        NOTREACHED();
        break;
      }
    }
  }
  return error;
}

void SupervisedUserSyncService::OnLastSignedInUsernameChange() {
  DCHECK(!sync_processor_);

  // If the last signed in user changes, we clear all data, to avoid supervised
  // users from one custodian appearing in another one's profile.
  prefs_->ClearPref(prefs::kSupervisedUsers);
}

void SupervisedUserSyncService::NotifySupervisedUserAcknowledged(
    const std::string& supervised_user_id) {
  FOR_EACH_OBSERVER(SupervisedUserSyncServiceObserver, observers_,
                    OnSupervisedUserAcknowledged(supervised_user_id));
}

void SupervisedUserSyncService::NotifySupervisedUsersSyncingStopped() {
  FOR_EACH_OBSERVER(SupervisedUserSyncServiceObserver, observers_,
                    OnSupervisedUsersSyncingStopped());
}

void SupervisedUserSyncService::NotifySupervisedUsersChanged() {
  FOR_EACH_OBSERVER(SupervisedUserSyncServiceObserver,
                    observers_,
                    OnSupervisedUsersChanged());
}

void SupervisedUserSyncService::DispatchCallbacks() {
  const base::DictionaryValue* supervised_users =
      prefs_->GetDictionary(prefs::kSupervisedUsers);
  for (std::vector<SupervisedUsersCallback>::iterator it = callbacks_.begin();
       it != callbacks_.end(); ++it) {
    it->Run(supervised_users);
  }
  callbacks_.clear();
}
