/*
 *  Copyright (c) 2013 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 WEBRTC_COMMON_H_
#define WEBRTC_COMMON_H_

#include <map>

namespace webrtc {

// Class Config is designed to ease passing a set of options across webrtc code.
// Options are identified by typename in order to avoid incorrect casts.
//
// Usage:
// * declaring an option:
//    struct Algo1_CostFunction {
//      virtual float cost(int x) const { return x; }
//      virtual ~Algo1_CostFunction() {}
//    };
//
// * accessing an option:
//    config.Get<Algo1_CostFunction>().cost(value);
//
// * setting an option:
//    struct SqrCost : Algo1_CostFunction {
//      virtual float cost(int x) const { return x*x; }
//    };
//    config.Set<Algo1_CostFunction>(new SqrCost());
//
// Note: This class is thread-compatible (like STL containers).
class Config {
 public:
  // Returns the option if set or a default constructed one.
  // Callers that access options too often are encouraged to cache the result.
  // Returned references are owned by this.
  //
  // Requires std::is_default_constructible<T>
  template<typename T> const T& Get() const;

  // Set the option, deleting any previous instance of the same.
  // This instance gets ownership of the newly set value.
  template<typename T> void Set(T* value);

  Config() {}
  ~Config() {
    // Note: this method is inline so webrtc public API depends only
    // on the headers.
    for (OptionMap::iterator it = options_.begin();
         it != options_.end(); ++it) {
      delete it->second;
    }
  }

 private:
  typedef void* OptionIdentifier;

  struct BaseOption {
    virtual ~BaseOption() {}
  };

  template<typename T>
  struct Option : BaseOption {
    explicit Option(T* v): value(v) {}
    ~Option() {
      delete value;
    }
    T* value;
  };

  // Own implementation of rtti-subset to avoid depending on rtti and its costs.
  template<typename T>
  static OptionIdentifier identifier() {
    static char id_placeholder;
    return &id_placeholder;
  }

  // Used to instantiate a default constructed object that doesn't needs to be
  // owned. This allows Get<T> to be implemented without requiring explicitly
  // locks.
  template<typename T>
  static const T& default_value() {
    static const T def;
    return def;
  }

  typedef std::map<OptionIdentifier, BaseOption*> OptionMap;
  OptionMap options_;

  // DISALLOW_COPY_AND_ASSIGN
  Config(const Config&);
  void operator=(const Config&);
};

template<typename T>
const T& Config::Get() const {
  OptionMap::const_iterator it = options_.find(identifier<T>());
  if (it != options_.end()) {
    const T* t = static_cast<Option<T>*>(it->second)->value;
    if (t) {
      return *t;
    }
  }
  return default_value<T>();
}

template<typename T>
void Config::Set(T* value) {
  BaseOption*& it = options_[identifier<T>()];
  delete it;
  it = new Option<T>(value);
}

}  // namespace webrtc

#endif  // WEBRTC_COMMON_H_
