/*
 * 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/route.hpp"
#include "vom/singular_db.hpp"

#include <vapi/ip.api.vapi.hpp>

namespace VOM {
namespace route {
singular_db<ip_route::key_t, ip_route> ip_route::m_db;

const path::special_t path::special_t::STANDARD(0, "standard");
const path::special_t path::special_t::LOCAL(0, "local");
const path::special_t path::special_t::DROP(0, "standard");
const path::special_t path::special_t::UNREACH(0, "unreachable");
const path::special_t path::special_t::PROHIBIT(0, "prohibit");

path::special_t::special_t(int v, const std::string& s)
  : enum_base<path::special_t>(v, s)
{
}

path::path(special_t special)
  : m_type(special)
  , m_nh_proto(nh_proto_t::IPV4)
  , m_nh()
  , m_rd(nullptr)
  , m_interface(nullptr)
  , m_weight(1)
  , m_preference(0)
{
}

path::path(const boost::asio::ip::address& nh,
           const interface& interface,
           uint8_t weight,
           uint8_t preference)
  : m_type(special_t::STANDARD)
  , m_nh_proto(nh_proto_t::from_address(nh))
  , m_nh(nh)
  , m_rd(nullptr)
  , m_interface(interface.singular())
  , m_weight(weight)
  , m_preference(preference)
{
}

path::path(const route_domain& rd,
           const boost::asio::ip::address& nh,
           uint8_t weight,
           uint8_t preference)
  : m_type(special_t::STANDARD)
  , m_nh_proto(nh_proto_t::from_address(nh))
  , m_nh(nh)
  , m_rd(rd.singular())
  , m_interface(nullptr)
  , m_weight(weight)
  , m_preference(preference)
{
}

path::path(const interface& interface,
           const nh_proto_t& proto,
           uint8_t weight,
           uint8_t preference)
  : m_type(special_t::STANDARD)
  , m_nh_proto(proto)
  , m_nh()
  , m_rd(nullptr)
  , m_interface(interface.singular())
  , m_weight(weight)
  , m_preference(preference)
{
}

path::path(const path& p)
  : m_type(p.m_type)
  , m_nh_proto(p.m_nh_proto)
  , m_nh(p.m_nh)
  , m_rd(p.m_rd)
  , m_interface(p.m_interface)
  , m_weight(p.m_weight)
  , m_preference(p.m_preference)
{
}

bool
path::operator<(const path& p) const
{
  if (m_type < p.m_type)
    return true;
  if (m_rd->table_id() < p.m_rd->table_id())
    return true;
  if (m_nh < p.m_nh)
    return true;
  if (m_interface->handle() < p.m_interface->handle())
    return true;

  return (false);
}

void
path::to_vpp(vapi_payload_ip_add_del_route& payload) const
{
  payload.is_drop = 0;
  payload.is_unreach = 0;
  payload.is_prohibit = 0;
  payload.is_local = 0;
  payload.is_classify = 0;
  payload.is_multipath = 0;
  payload.is_resolve_host = 0;
  payload.is_resolve_attached = 0;

  if (nh_proto_t::ETHERNET == m_nh_proto) {
    payload.is_l2_bridged = 1;
  }

  if (special_t::STANDARD == m_type) {
    uint8_t path_v6;
    to_bytes(m_nh, &path_v6, payload.next_hop_address);

    if (m_rd) {
      payload.next_hop_table_id = m_rd->table_id();
    }
    if (m_interface) {
      payload.next_hop_sw_if_index = m_interface->handle().value();
    }
  } else if (special_t::DROP == m_type) {
    payload.is_drop = 1;
  } else if (special_t::UNREACH == m_type) {
    payload.is_unreach = 1;
  } else if (special_t::PROHIBIT == m_type) {
    payload.is_prohibit = 1;
  } else if (special_t::LOCAL == m_type) {
    payload.is_local = 1;
  }
  payload.next_hop_weight = m_weight;
  payload.next_hop_preference = m_preference;
  payload.next_hop_via_label = 0;
  payload.classify_table_index = 0;
}

std::string
path::to_string() const
{
  std::ostringstream s;

  s << "path:["
    << "type:" << m_type.to_string() << " proto:" << m_nh_proto.to_string()
    << " neighbour:" << m_nh.to_string();
  if (m_rd) {
    s << " " << m_rd->to_string();
  }
  if (m_interface) {
    s << " " << m_interface->to_string();
  }
  s << " weight:" << static_cast<int>(m_weight)
    << " preference:" << static_cast<int>(m_preference) << "]";

  return (s.str());
}

ip_route::ip_route(const prefix_t& prefix)
  : m_hw(false)
  , m_rd(route_domain::get_default())
  , m_prefix(prefix)
  , m_paths()
{
}

ip_route::ip_route(const ip_route& r)
  : m_hw(r.m_hw)
  , m_rd(r.m_rd)
  , m_prefix(r.m_prefix)
  , m_paths(r.m_paths)
{
}

ip_route::ip_route(const route_domain& rd, const prefix_t& prefix)
  : m_hw(false)
  , m_rd(rd.singular())
  , m_prefix(prefix)
  , m_paths()
{
}

ip_route::~ip_route()
{
  sweep();

  // not in the DB anymore.
  m_db.release(std::make_pair(m_rd->table_id(), m_prefix), this);
}

void
ip_route::add(const path& path)
{
  m_paths.insert(path);
}

void
ip_route::remove(const path& path)
{
  m_paths.erase(path);
}

void
ip_route::sweep()
{
  if (m_hw) {
    HW::enqueue(new delete_cmd(m_hw, m_rd->table_id(), m_prefix));
  }
  HW::write();
}

void
ip_route::replay()
{
  if (m_hw) {
    HW::enqueue(new update_cmd(m_hw, m_rd->table_id(), m_prefix, m_paths));
  }
}
std::string
ip_route::to_string() const
{
  std::ostringstream s;
  s << "route:[" << m_rd->to_string() << ", " << m_prefix.to_string() << " ["
    << m_paths << "]"
    << "]";

  return (s.str());
}

void
ip_route::update(const ip_route& r)
{
  /*
* create the table if it is not yet created
*/
  if (rc_t::OK != m_hw.rc()) {
    HW::enqueue(new update_cmd(m_hw, m_rd->table_id(), m_prefix, m_paths));
  }
}

std::shared_ptr<ip_route>
ip_route::find_or_add(const ip_route& temp)
{
  return (m_db.find_or_add(std::make_pair(temp.m_rd->table_id(), temp.m_prefix),
                           temp));
}

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

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

ip_route::event_handler::event_handler()
{
  OM::register_listener(this);
  inspect::register_handler({ "ip-route" }, "ip route configurations", this);
}

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

void
ip_route::event_handler::handle_populate(const client_db::key_t& key)
{
  std::shared_ptr<ip_route::dump_v4_cmd> cmd_v4(new ip_route::dump_v4_cmd());
  std::shared_ptr<ip_route::dump_v6_cmd> cmd_v6(new ip_route::dump_v6_cmd());

  HW::enqueue(cmd_v4);
  HW::enqueue(cmd_v6);
  HW::write();

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

    prefix_t pfx(0, payload.address, payload.address_length);

    /**
* populating the route domain here
*/
    route_domain rd_temp(payload.table_id);
    std::shared_ptr<route_domain> rd = route_domain::find(rd_temp);
    if (!rd) {
      OM::commit(key, rd_temp);
    }
    ip_route ip_r(rd_temp, pfx);

    for (unsigned int i = 0; i < payload.count; i++) {
      vapi_type_fib_path p = payload.path[i];
      if (p.is_local) {
        path path_v4(path::special_t::LOCAL);
        ip_r.add(path_v4);
      } else if (p.is_drop) {
        path path_v4(path::special_t::DROP);
        ip_r.add(path_v4);
      } else if (p.is_unreach) {
        path path_v4(path::special_t::UNREACH);
        ip_r.add(path_v4);
      } else if (p.is_prohibit) {
        path path_v4(path::special_t::PROHIBIT);
        ip_r.add(path_v4);
      } else {
        std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
        boost::asio::ip::address address = from_bytes(0, p.next_hop);
        path path_v4(address, *itf, p.weight, p.preference);
        ip_r.add(path_v4);
      }
    }
    VOM_LOG(log_level_t::DEBUG) << "ip-route-dump: " << ip_r.to_string();

    /*
* Write each of the discovered interfaces into the OM,
* but disable the HW Command q whilst we do, so that no
* commands are sent to VPP
*/
    OM::commit(key, ip_r);
  }

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

    prefix_t pfx(1, payload.address, payload.address_length);
    route_domain rd_temp(payload.table_id);
    std::shared_ptr<route_domain> rd = route_domain::find(rd_temp);
    if (!rd) {
      OM::commit(key, rd_temp);
    }
    ip_route ip_r(rd_temp, pfx);

    for (unsigned int i = 0; i < payload.count; i++) {
      vapi_type_fib_path p = payload.path[i];
      if (p.is_local) {
        path path_v6(path::special_t::LOCAL);
        ip_r.add(path_v6);
      } else if (p.is_drop) {
        path path_v6(path::special_t::DROP);
        ip_r.add(path_v6);
      } else if (p.is_unreach) {
        path path_v6(path::special_t::UNREACH);
        ip_r.add(path_v6);
      } else if (p.is_prohibit) {
        path path_v6(path::special_t::PROHIBIT);
        ip_r.add(path_v6);
      } else {
        std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
        boost::asio::ip::address address = from_bytes(1, p.next_hop);
        path path_v6(address, *itf, p.weight, p.preference);
        ip_r.add(path_v6);
      }
    }
    VOM_LOG(log_level_t::DEBUG) << "ip-route-dump: " << ip_r.to_string();

    /*
* Write each of the discovered interfaces into the OM,
* but disable the HW Command q whilst we do, so that no
* commands are sent to VPP
*/
    OM::commit(key, ip_r);
  }
}

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

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

std::ostream&
operator<<(std::ostream& os, const ip_route::key_t& key)
{
  os << "[" << key.first << ", " << key.second.to_string() << "]";

  return (os);
}

std::ostream&
operator<<(std::ostream& os, const path_list_t& key)
{
  os << "[";
  for (auto k : key) {
    os << k.to_string() << " ";
  }
  os << "]";

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