/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "cobalt/base/c_val.h"

#include <sstream>

namespace base {

CValManager* CValManager::GetInstance() {
  return Singleton<CValManager,
                   StaticMemorySingletonTraits<CValManager> >::get();
}

CValManager::CValManager() {
  // Allocate these dynamically since CValManager may live across DLL boundaries
  // and so this allows its size to be more consistent (and avoids compiler
  // warnings on some platforms).
  registered_vars_ = new NameVarMap();
#if defined(ENABLE_DEBUG_C_VAL)
  on_changed_hook_set_ = new base::hash_set<OnChangedHook*>();
#endif  // ENABLE_DEBUG_C_VAL
}

CValManager::~CValManager() {
#if defined(ENABLE_DEBUG_C_VAL)
  delete on_changed_hook_set_;
#endif  // ENABLE_DEBUG_C_VAL
  delete registered_vars_;
}

void CValManager::RegisterCVal(const CValDetail::CValBase* cval) {
  base::AutoLock auto_lock(cvals_lock_);

  // CVals cannot share name.  If this assert is triggered, we are trying to
  // register more than one CVal with the same name, which this system is
  // not designed to handle.
  DCHECK(registered_vars_->find(cval->GetName()) == registered_vars_->end());

  (*registered_vars_)[cval->GetName()] = cval;
}

void CValManager::UnregisterCVal(const CValDetail::CValBase* cval) {
  base::AutoLock auto_lock(cvals_lock_);

  NameVarMap::iterator found = registered_vars_->find(cval->GetName());
  DCHECK(found != registered_vars_->end());
  if (found != registered_vars_->end()) {
    registered_vars_->erase(found);
  }
}

#if defined(ENABLE_DEBUG_C_VAL)
void CValManager::PushValueChangedEvent(const CValDetail::CValBase* cval,
                                        const CValGenericValue& value) {
  base::AutoLock auto_lock(hooks_lock_);

  // Iterate through the hooks sending each of them the value changed event.
  for (OnChangeHookSet::iterator iter = on_changed_hook_set_->begin();
       iter != on_changed_hook_set_->end(); ++iter) {
    (*iter)->OnValueChanged(cval->GetName(), value);
  }
}

CValManager::OnChangedHook::OnChangedHook() {
  CValManager* cvm = CValManager::GetInstance();
  base::AutoLock auto_lock(cvm->hooks_lock_);

  // Register this hook with the CValManager
  bool was_inserted ALLOW_UNUSED =
      cvm->on_changed_hook_set_->insert(this).second;
  DCHECK(was_inserted);
}

CValManager::OnChangedHook::~OnChangedHook() {
  CValManager* cvm = CValManager::GetInstance();
  base::AutoLock auto_lock(cvm->hooks_lock_);

  // Deregister this hook with the CValManager
  size_t values_erased ALLOW_UNUSED = cvm->on_changed_hook_set_->erase(this);
  DCHECK_EQ(values_erased, 1);
}
#endif  // ENABLE_DEBUG_C_VAL

std::set<std::string> CValManager::GetOrderedCValNames() {
  std::set<std::string> ret;
  base::AutoLock auto_lock(cvals_lock_);

  // Return all registered CVal names, as an std::set to show they are sorted.
  for (NameVarMap::const_iterator iter = registered_vars_->begin();
       iter != registered_vars_->end(); ++iter) {
    ret.insert(iter->first);
  }

  return ret;
}

optional<std::string> CValManager::GetCValStringValue(const std::string& name,
                                                      bool pretty) {
  base::AutoLock auto_lock(cvals_lock_);

  // Return the value of a CVal, if it exists.  If it does not exist,
  // indicate that it does not exist.
  NameVarMap::const_iterator found = registered_vars_->find(name);
  if (found == registered_vars_->end()) {
    return nullopt;
  } else {
    return (pretty ? found->second->GetValueAsPrettyString()
                   : found->second->GetValueAsString());
  }
}

optional<std::string> CValManager::GetValueAsString(const std::string& name) {
  return GetCValStringValue(name, false);
}

optional<std::string> CValManager::GetValueAsPrettyString(
    const std::string& name) {
  return GetCValStringValue(name, true);
}

}  // namespace base
