/*
 * 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 "vom/nat_binding.hpp"
#include "vom/cmd.hpp"
#include "vom/nat_binding_cmds.hpp"

namespace VOM {
singular_db<const nat_binding::key_t, nat_binding> nat_binding::m_db;

nat_binding::event_handler nat_binding::m_evh;

const nat_binding::zone_t nat_binding::zone_t::INSIDE(0, "inside");
const nat_binding::zone_t nat_binding::zone_t::OUTSIDE(0, "outside");

nat_binding::zone_t::zone_t(int v, const std::string s)
  : enum_base(v, s)
{
}
const nat_binding::zone_t&
nat_binding::zone_t::from_vpp(u8 is_inside)
{
  if (is_inside)
    return zone_t::INSIDE;
  return zone_t::OUTSIDE;
}

/**
 * Construct a new object matching the desried state
 */
nat_binding::nat_binding(const interface& itf,
                         const direction_t& dir,
                         const l3_proto_t& proto,
                         const zone_t& zone)
  : m_binding(false)
  , m_itf(itf.singular())
  , m_dir(dir)
  , m_proto(proto)
  , m_zone(zone)
{
}

nat_binding::nat_binding(const nat_binding& o)
  : m_binding(o.m_binding)
  , m_itf(o.m_itf)
  , m_dir(o.m_dir)
  , m_proto(o.m_proto)
  , m_zone(o.m_zone)
{
}

nat_binding::~nat_binding()
{
  sweep();
  m_db.release(key(), this);
}

const nat_binding::key_t
nat_binding::key() const
{
  return (make_tuple(m_itf->key(), m_dir, m_proto));
}

bool
nat_binding::operator==(const nat_binding& n) const
{
  return ((key() == n.key()) && (m_zone == n.m_zone));
}

void
nat_binding::sweep()
{
  if (m_binding) {
    if (direction_t::INPUT == m_dir) {
      HW::enqueue(new nat_binding_cmds::unbind_44_input_cmd(
        m_binding, m_itf->handle(), m_zone));
    } else {
      HW::enqueue(new nat_binding_cmds::unbind_44_output_cmd(
        m_binding, m_itf->handle(), m_zone));
    }
  }
  HW::write();
}

void
nat_binding::replay()
{
  if (m_binding) {
    if (direction_t::INPUT == m_dir) {
      HW::enqueue(new nat_binding_cmds::bind_44_input_cmd(
        m_binding, m_itf->handle(), m_zone));
    } else {
      HW::enqueue(new nat_binding_cmds::bind_44_output_cmd(
        m_binding, m_itf->handle(), m_zone));
    }
  }
}

void
nat_binding::update(const nat_binding& desired)
{
  /*
 * the desired state is always that the interface should be created
 */
  if (!m_binding) {
    if (direction_t::INPUT == m_dir) {
      HW::enqueue(new nat_binding_cmds::bind_44_input_cmd(
        m_binding, m_itf->handle(), m_zone));
    } else {
      HW::enqueue(new nat_binding_cmds::bind_44_input_cmd(
        m_binding, m_itf->handle(), m_zone));
    }
  }
}

std::string
nat_binding::to_string() const
{
  std::ostringstream s;
  s << "nat-binding:[" << m_itf->to_string()
    << " direction:" << m_dir.to_string() << " proto:" << m_proto.to_string()
    << " zone:" << m_zone.to_string() << "]";

  return (s.str());
}

std::shared_ptr<nat_binding>
nat_binding::find_or_add(const nat_binding& temp)
{
  return (m_db.find_or_add(temp.key(), temp));
}

std::shared_ptr<nat_binding>
nat_binding::find(const key_t& key)
{
  return (m_db.find(key));
}

std::shared_ptr<nat_binding>
nat_binding::singular() const
{
  return find_or_add(*this);
}

void
nat_binding::dump(std::ostream& os)
{
  m_db.dump(os);
}

std::ostream&
operator<<(std::ostream& os, const nat_binding::key_t& key)
{
  os << "[" << std::get<0>(key) << ", " << std::get<1>(key) << ", "
     << std::get<2>(key) << "]";

  return (os);
}

nat_binding::event_handler::event_handler()
{
  OM::register_listener(this);
  inspect::register_handler({ "nat-binding" }, "NAT bindings", this);
}

void
nat_binding::event_handler::handle_replay()
{
  m_db.replay();
}

void
nat_binding::event_handler::handle_populate(const client_db::key_t& key)
{
  std::shared_ptr<nat_binding_cmds::dump_input_44_cmd> icmd =
    std::make_shared<nat_binding_cmds::dump_input_44_cmd>();

  HW::enqueue(icmd);
  HW::write();

  for (auto& record : *icmd) {
    auto& payload = record.get_payload();

    std::shared_ptr<interface> itf = interface::find(payload.sw_if_index);
    nat_binding nb(*itf, direction_t::INPUT, l3_proto_t::IPV4,
                   zone_t::from_vpp(payload.is_inside));
    OM::commit(key, nb);
  }

  std::shared_ptr<nat_binding_cmds::dump_output_44_cmd> ocmd =
    std::make_shared<nat_binding_cmds::dump_output_44_cmd>();

  HW::enqueue(ocmd);
  HW::write();

  for (auto& record : *ocmd) {
    auto& payload = record.get_payload();

    std::shared_ptr<interface> itf = interface::find(payload.sw_if_index);
    nat_binding nb(*itf, direction_t::OUTPUT, l3_proto_t::IPV4,
                   zone_t::from_vpp(payload.is_inside));
    OM::commit(key, nb);
  }
}

dependency_t
nat_binding::event_handler::order() const
{
  return (dependency_t::BINDING);
}

void
nat_binding::event_handler::show(std::ostream& os)
{
  m_db.dump(os);
}
}

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