/*
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * 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 <algorithm>

#include "vom/logger.hpp"
#include "vom/om.hpp"

namespace VOM {
client_db* OM::m_db;

std::unique_ptr<OM::listener_list> OM::m_listeners;

/**
 * Initialse the connection to VPP
 */
void
OM::init()
{
  m_db = new client_db();
}

void
OM::mark(const client_db::key_t& key)
{
  /*
 * Find if the object already stored on behalf of this key.
 * and mark them stale
 */
  object_ref_list& objs = m_db->find(key);

  auto mark_obj = [](const object_ref& oref) { oref.mark(); };

  std::for_each(objs.begin(), objs.end(), mark_obj);
}

void
OM::sweep(const client_db::key_t& key)
{
  /*
   * Find if the object already stored on behalf of this key.
   * and mark them stale
   */
  object_ref_list& objs = m_db->find(key);

  for (auto it = objs.begin(); it != objs.end();) {
    if (it->stale()) {
      it = objs.erase(it);
    } else {
      ++it;
    }
  }

  HW::write();
}

void
OM::remove(const client_db::key_t& key)
{
  /*
   * Simply reset the list for this key. This will desctruct the
   * object list and shared_ptrs therein. When the last shared_ptr
   * goes the objects desctructor is called and the object is
   * removed from OM
   */
  m_db->flush(key);

  HW::write();
}

void
OM::replay()
{
  VOM_LOG(log_level_t::INFO) << "replay";
  /*
   * the listeners are sorted in dependency order
   */
  for (listener* l : *m_listeners) {
    l->handle_replay();
    HW::write();
  }
}

void
OM::dump(const client_db::key_t& key, std::ostream& os)
{
  m_db->dump(key, os);
}

void
OM::dump(std::ostream& os)
{
  m_db->dump(os);
}

void
OM::populate(const client_db::key_t& key)
{
  VOM_LOG(log_level_t::INFO) << "populate";

  /*
   * the listeners are sorted in dependency order
   */
  for (listener* l : *m_listeners) {
    l->handle_populate(key);
  }

  /*
   * once we have it all, mark it stale.
   */
  mark(key);
}

bool
OM::register_listener(OM::listener* listener)
{
  if (!m_listeners) {
    m_listeners.reset(new listener_list);
  }

  m_listeners->insert(listener);

  return (true);
}

OM::mark_n_sweep::mark_n_sweep(const client_db::key_t& key)
  : m_key(key)
{
  OM::mark(m_key);
}

OM::mark_n_sweep::~mark_n_sweep()
{
  OM::sweep(m_key);
}
}

/*
 * fd.io coding-style-patch-verification: OFF
 *
 * Local Variables:
 * eval: (c-set-style "mozilla")
 * End:
 */
