/*
 *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#ifndef RTC_BASE_EXPERIMENTS_FIELD_TRIAL_LIST_H_
#define RTC_BASE_EXPERIMENTS_FIELD_TRIAL_LIST_H_

#include <initializer_list>
#include <memory>
#include <string>
#include <vector>

#include "absl/strings/string_view.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/string_encode.h"

// List support for field trial strings. FieldTrialList and FieldTrialStructList
// are used similarly to the other FieldTrialParameters, but take a variable
// number of parameters. A FieldTrialList<T> parses a |-delimeted string into a
// list of T, using ParseTypedParameter to parse the individual tokens.
// Example string: "my_list:1|2|3,empty_list,other_list:aardvark".

// A FieldTrialStructList combines multiple lists into a list-of-structs. It
// ensures that all its sublists parse correctly and have the same length, then
// uses user-supplied accessor functions to write those elements into structs of
// a user-supplied type.

// See the unit test for usage and behavior.

namespace webrtc {

class FieldTrialListBase : public FieldTrialParameterInterface {
 protected:
  friend class FieldTrialListWrapper;
  explicit FieldTrialListBase(absl::string_view key);

  bool Failed() const;
  bool Used() const;

  virtual int Size() = 0;

  bool failed_;
  bool parse_got_called_;
};

// This class represents a vector of type T. The elements are separated by a |
// and parsed using ParseTypedParameter.
template <typename T>
class FieldTrialList : public FieldTrialListBase {
 public:
  explicit FieldTrialList(absl::string_view key) : FieldTrialList(key, {}) {}
  FieldTrialList(absl::string_view key, std::initializer_list<T> default_values)
      : FieldTrialListBase(key), values_(default_values) {}

  std::vector<T> Get() const { return values_; }
  operator std::vector<T>() const { return Get(); }
  typename std::vector<T>::const_reference operator[](size_t index) const {
    return values_[index];
  }
  const std::vector<T>* operator->() const { return &values_; }

 protected:
  bool Parse(absl::optional<std::string> str_value) override {
    parse_got_called_ = true;

    if (!str_value) {
      values_.clear();
      return true;
    }

    std::vector<T> new_values_;

    for (const absl::string_view token : rtc::split(str_value.value(), '|')) {
      absl::optional<T> value = ParseTypedParameter<T>(token);
      if (value) {
        new_values_.push_back(*value);
      } else {
        failed_ = true;
        return false;
      }
    }

    values_.swap(new_values_);
    return true;
  }

  int Size() override { return values_.size(); }

 private:
  std::vector<T> values_;
};

class FieldTrialListWrapper {
 public:
  virtual ~FieldTrialListWrapper() = default;

  // Takes the element at the given index in the wrapped list and writes it to
  // the given struct.
  virtual void WriteElement(void* struct_to_write, int index) = 0;

  virtual FieldTrialListBase* GetList() = 0;

  int Length();

  // Returns true iff the wrapped list has failed to parse at least one token.
  bool Failed();

  bool Used();

 protected:
  FieldTrialListWrapper() = default;
};

namespace field_trial_list_impl {
// The LambdaTypeTraits struct provides type information about lambdas in the
// template expressions below.
template <typename T>
struct LambdaTypeTraits : public LambdaTypeTraits<decltype(&T::operator())> {};

template <typename ClassType, typename RetType, typename SourceType>
struct LambdaTypeTraits<RetType* (ClassType::*)(SourceType*) const> {
  using ret = RetType;
  using src = SourceType;
};

template <typename T>
struct TypedFieldTrialListWrapper : FieldTrialListWrapper {
 public:
  TypedFieldTrialListWrapper(absl::string_view key,
                             std::function<void(void*, T)> sink)
      : list_(key), sink_(sink) {}

  void WriteElement(void* struct_to_write, int index) override {
    sink_(struct_to_write, list_[index]);
  }

  FieldTrialListBase* GetList() override { return &list_; }

 private:
  FieldTrialList<T> list_;
  std::function<void(void*, T)> sink_;
};

}  // namespace field_trial_list_impl

template <typename F,
          typename Traits = typename field_trial_list_impl::LambdaTypeTraits<F>>
FieldTrialListWrapper* FieldTrialStructMember(absl::string_view key,
                                              F accessor) {
  return new field_trial_list_impl::TypedFieldTrialListWrapper<
      typename Traits::ret>(key, [accessor](void* s, typename Traits::ret t) {
    *accessor(static_cast<typename Traits::src*>(s)) = t;
  });
}

// This base class is here to reduce the amount of code we have to generate for
// each type of FieldTrialStructList.
class FieldTrialStructListBase : public FieldTrialParameterInterface {
 protected:
  FieldTrialStructListBase(
      std::initializer_list<FieldTrialListWrapper*> sub_lists)
      : FieldTrialParameterInterface(""), sub_lists_() {
    // Take ownership of the list wrappers generated by FieldTrialStructMember
    // on the call site.
    for (FieldTrialListWrapper* const* it = sub_lists.begin();
         it != sub_lists.end(); it++) {
      sub_parameters_.push_back((*it)->GetList());
      sub_lists_.push_back(std::unique_ptr<FieldTrialListWrapper>(*it));
    }
  }

  // Check that all of our sublists that were in the field trial string had the
  // same number of elements. If they do, we return that length. If they had
  // different lengths, any sublist had parse failures or no sublists had
  // user-supplied values, we return -1.
  int ValidateAndGetLength();

  bool Parse(absl::optional<std::string> str_value) override;

  std::vector<std::unique_ptr<FieldTrialListWrapper>> sub_lists_;
};

template <typename S>
class FieldTrialStructList : public FieldTrialStructListBase {
 public:
  FieldTrialStructList(std::initializer_list<FieldTrialListWrapper*> l,
                       std::initializer_list<S> default_list)
      : FieldTrialStructListBase(l), values_(default_list) {}

  std::vector<S> Get() const { return values_; }
  operator std::vector<S>() const { return Get(); }
  const S& operator[](size_t index) const { return values_[index]; }
  const std::vector<S>* operator->() const { return &values_; }

 protected:
  void ParseDone() override {
    int length = ValidateAndGetLength();

    if (length == -1)
      return;

    std::vector<S> new_values(length, S());

    for (std::unique_ptr<FieldTrialListWrapper>& li : sub_lists_) {
      if (li->Used()) {
        for (int i = 0; i < length; i++) {
          li->WriteElement(&new_values[i], i);
        }
      }
    }

    values_.swap(new_values);
  }

 private:
  std::vector<S> values_;
};

}  // namespace webrtc

#endif  // RTC_BASE_EXPERIMENTS_FIELD_TRIAL_LIST_H_
