// Copyright 2013 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 "components/variations/variations_associated_data.h"

#include <map>
#include <utility>
#include <vector>

#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/strings/string_split.h"
#include "components/variations/variations_http_header_provider.h"

namespace variations {

namespace {

const char kGroupTesting[] = "Testing";

// The internal singleton accessor for the map, used to keep it thread-safe.
class GroupMapAccessor {
 public:
  typedef std::map<ActiveGroupId, VariationID, ActiveGroupIdCompare>
      GroupToIDMap;

  // Retrieve the singleton.
  static GroupMapAccessor* GetInstance() {
    return base::Singleton<GroupMapAccessor>::get();
  }

  // Note that this normally only sets the ID for a group the first time, unless
  // |force| is set to true, in which case it will always override it.
  void AssociateID(IDCollectionKey key,
                   const ActiveGroupId& group_identifier,
                   const VariationID id,
                   const bool force) {
#if !defined(NDEBUG)
    DCHECK_EQ(4, ID_COLLECTION_COUNT);
    // Ensure that at most one of the trigger/non-trigger web property IDs are
    // set.
    if (key == GOOGLE_WEB_PROPERTIES || key == GOOGLE_WEB_PROPERTIES_TRIGGER) {
      IDCollectionKey other_key = key == GOOGLE_WEB_PROPERTIES ?
          GOOGLE_WEB_PROPERTIES_TRIGGER : GOOGLE_WEB_PROPERTIES;
      DCHECK_EQ(EMPTY_ID, GetID(other_key, group_identifier));
    }

    // Validate that all collections with this |group_identifier| have the same
    // associated ID.
    for (int i = 0; i < ID_COLLECTION_COUNT; ++i) {
      IDCollectionKey other_key = static_cast<IDCollectionKey>(i);
      if (other_key == key)
        continue;
      VariationID other_id = GetID(other_key, group_identifier);
      DCHECK(other_id == EMPTY_ID || other_id == id);
    }
#endif

    base::AutoLock scoped_lock(lock_);

    GroupToIDMap* group_to_id_map = GetGroupToIDMap(key);
    if (force ||
        group_to_id_map->find(group_identifier) == group_to_id_map->end())
      (*group_to_id_map)[group_identifier] = id;
  }

  VariationID GetID(IDCollectionKey key,
                    const ActiveGroupId& group_identifier) {
    base::AutoLock scoped_lock(lock_);
    GroupToIDMap* group_to_id_map = GetGroupToIDMap(key);
    GroupToIDMap::const_iterator it = group_to_id_map->find(group_identifier);
    if (it == group_to_id_map->end())
      return EMPTY_ID;
    return it->second;
  }

  void ClearAllMapsForTesting() {
    base::AutoLock scoped_lock(lock_);

    for (int i = 0; i < ID_COLLECTION_COUNT; ++i) {
      GroupToIDMap* map = GetGroupToIDMap(static_cast<IDCollectionKey>(i));
      DCHECK(map);
      map->clear();
    }
  }

 private:
  friend struct base::DefaultSingletonTraits<GroupMapAccessor>;

  // Retrieves the GroupToIDMap for |key|.
  GroupToIDMap* GetGroupToIDMap(IDCollectionKey key) {
    return &group_to_id_maps_[key];
  }

  GroupMapAccessor() {
    group_to_id_maps_.resize(ID_COLLECTION_COUNT);
  }
  ~GroupMapAccessor() {}

  base::Lock lock_;
  std::vector<GroupToIDMap> group_to_id_maps_;

  DISALLOW_COPY_AND_ASSIGN(GroupMapAccessor);
};

// Singleton helper class that keeps track of the parameters of all variations
// and ensures access to these is thread-safe.
class VariationsParamAssociator {
 public:
  typedef std::pair<std::string, std::string> VariationKey;
  typedef std::map<std::string, std::string> VariationParams;

  // Retrieve the singleton.
  static VariationsParamAssociator* GetInstance() {
    return base::Singleton<
        VariationsParamAssociator,
        base::LeakySingletonTraits<VariationsParamAssociator>>::get();
  }

  bool AssociateVariationParams(const std::string& trial_name,
                                const std::string& group_name,
                                const VariationParams& params) {
    base::AutoLock scoped_lock(lock_);

    if (base::FieldTrialList::IsTrialActive(trial_name))
      return false;

    const VariationKey key(trial_name, group_name);
    if (base::ContainsKey(variation_params_, key))
      return false;

    variation_params_[key] = params;
    return true;
  }

  bool GetVariationParams(const std::string& trial_name,
                          VariationParams* params) {
    base::AutoLock scoped_lock(lock_);

    const std::string group_name =
        base::FieldTrialList::FindFullName(trial_name);
    const VariationKey key(trial_name, group_name);
    if (!base::ContainsKey(variation_params_, key))
      return false;

    *params = variation_params_[key];
    return true;
  }

  void ClearAllParamsForTesting() {
    base::AutoLock scoped_lock(lock_);
    variation_params_.clear();
  }

 private:
  friend struct base::DefaultSingletonTraits<VariationsParamAssociator>;

  VariationsParamAssociator() {}
  ~VariationsParamAssociator() {}

  base::Lock lock_;
  std::map<VariationKey, VariationParams> variation_params_;

  DISALLOW_COPY_AND_ASSIGN(VariationsParamAssociator);
};

}  // namespace

void AssociateGoogleVariationID(IDCollectionKey key,
                                const std::string& trial_name,
                                const std::string& group_name,
                                VariationID id) {
  GroupMapAccessor::GetInstance()->AssociateID(
      key, MakeActiveGroupId(trial_name, group_name), id, false);
}

void AssociateGoogleVariationIDForce(IDCollectionKey key,
                                     const std::string& trial_name,
                                     const std::string& group_name,
                                     VariationID id) {
  AssociateGoogleVariationIDForceHashes(
      key, MakeActiveGroupId(trial_name, group_name), id);
}

void AssociateGoogleVariationIDForceHashes(IDCollectionKey key,
                                           const ActiveGroupId& active_group,
                                           VariationID id) {
  GroupMapAccessor::GetInstance()->AssociateID(key, active_group, id, true);
}

VariationID GetGoogleVariationID(IDCollectionKey key,
                                 const std::string& trial_name,
                                 const std::string& group_name) {
  return GetGoogleVariationIDFromHashes(
      key, MakeActiveGroupId(trial_name, group_name));
}

VariationID GetGoogleVariationIDFromHashes(
    IDCollectionKey key,
    const ActiveGroupId& active_group) {
  return GroupMapAccessor::GetInstance()->GetID(key, active_group);
}

bool AssociateVariationParams(
    const std::string& trial_name,
    const std::string& group_name,
    const std::map<std::string, std::string>& params) {
  return VariationsParamAssociator::GetInstance()->AssociateVariationParams(
      trial_name, group_name, params);
}

bool GetVariationParams(const std::string& trial_name,
                        std::map<std::string, std::string>* params) {
  return VariationsParamAssociator::GetInstance()->GetVariationParams(
      trial_name, params);
}

bool GetVariationParamsByFeature(const base::Feature& feature,
                                 std::map<std::string, std::string>* params) {
  if (!base::FeatureList::IsEnabled(feature))
    return false;

  base::FieldTrial* trial = base::FeatureList::GetFieldTrial(feature);
  if (!trial)
    return false;

  return GetVariationParams(trial->trial_name(), params);
}

std::string GetVariationParamValue(const std::string& trial_name,
                                   const std::string& param_name) {
  std::map<std::string, std::string> params;
  if (GetVariationParams(trial_name, &params)) {
    std::map<std::string, std::string>::iterator it = params.find(param_name);
    if (it != params.end())
      return it->second;
  }
  return std::string();
}

std::string GetVariationParamValueByFeature(const base::Feature& feature,
                                            const std::string& param_name) {
  if (!base::FeatureList::IsEnabled(feature))
    return std::string();

  base::FieldTrial* trial = base::FeatureList::GetFieldTrial(feature);
  if (!trial)
    return std::string();

  return GetVariationParamValue(trial->trial_name(), param_name);
}

// Functions below are exposed for testing explicitly behind this namespace.
// They simply wrap existing functions in this file.
namespace testing {

VariationParamsManager::VariationParamsManager(
    const std::string& trial_name,
    const std::map<std::string, std::string>& params) {
  SetVariationParams(trial_name, params);
}

VariationParamsManager::~VariationParamsManager() {
  ClearAllVariationIDs();
  ClearAllVariationParams();
  field_trial_list_.reset();
}

void VariationParamsManager::SetVariationParams(
    const std::string& trial_name,
    const std::map<std::string, std::string>& params) {
  field_trial_list_.reset(new base::FieldTrialList(nullptr));
  variations::AssociateVariationParams(trial_name, kGroupTesting, params);
  base::FieldTrialList::CreateFieldTrial(trial_name, kGroupTesting);
}

void ClearAllVariationIDs() {
  GroupMapAccessor::GetInstance()->ClearAllMapsForTesting();
}

void ClearAllVariationParams() {
  VariationsParamAssociator::GetInstance()->ClearAllParamsForTesting();
}

}  // namespace testing

}  // namespace variations
