/*
 *  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 "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(std::string 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(std::string key) : FieldTrialList(key, {}) {}
  FieldTrialList(std::string 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(); }
  const T& 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<std::string> tokens;
    std::vector<T> new_values_;
    rtc::split(str_value.value(), '|', &tokens);

    for (std::string token : tokens) {
      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(std::string 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(std::string 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_
