/*
 * Library of NC-SI commands compliant with version 1.0.0.
 *
 * This implements a subset of the commands provided in the specification.
 *
 * Checksums are optional and not implemented here. All NC-SI checksums are set
 * to 0 to indicate that per 8.2.2.3.
 */

#include <stdint.h>
#include <string.h>

#include <netinet/in.h>

#include "platforms/nemora/portable/ncsi.h"
#include "platforms/nemora/portable/ncsi_server.h"


void ncsi_build_response_header(const uint8_t* request_buf,
                                uint8_t* response_buf, uint16_t response_code,
                                uint16_t reason_code, uint16_t payload_length) {
  /* Copy the header from the command */
  memcpy(response_buf, request_buf, sizeof(ncsi_header_t));
  ncsi_simple_response_t* response = (ncsi_simple_response_t*)response_buf;
  response->response_code = response_code;
  response->reason_code = reason_code;

  const ncsi_header_t* request_header = (const ncsi_header_t*)request_buf;
  response->hdr.control_packet_type =
      request_header->control_packet_type | NCSI_RESPONSE;
  response->hdr.payload_length = htons(payload_length);
}

uint32_t ncsi_build_simple_ack(const uint8_t* request_buf,
                               uint8_t* response_buf) {
  /* Copy the header from the command */
  ncsi_build_response_header(
      request_buf, response_buf, 0, 0,
      sizeof(ncsi_simple_response_t) - sizeof(ncsi_header_t));

  return sizeof(ncsi_simple_response_t);
}

uint32_t ncsi_build_simple_nack(const uint8_t* request_buf,
                                uint8_t* response_buf, uint16_t response_code,
                                uint16_t reason_code) {
  ncsi_build_response_header(
      request_buf, response_buf, response_code, reason_code,
      sizeof(ncsi_simple_response_t) - sizeof(ncsi_header_t));

  return sizeof(ncsi_simple_response_t);
}

static void ncsi_build_oem_ack(const uint8_t* request_buf,
                               uint8_t* response_buf, uint32_t response_size) {
  ncsi_build_response_header(
      request_buf, response_buf, 0, 0,
      response_size - sizeof(ncsi_header_t));
  const ncsi_oem_simple_cmd_t* oem_command =
      (const ncsi_oem_simple_cmd_t*)request_buf;
  ncsi_oem_simple_response_t* oem_response =
      (ncsi_oem_simple_response_t*)response_buf;
  memmove(&oem_response->oem_header, &oem_command->oem_header,
          sizeof(ncsi_oem_extension_header_t));
  oem_response->oem_header.manufacturer_id = htonl(NCSI_OEM_MANUFACTURER_ID);
}

uint32_t ncsi_build_version_id_ack(const uint8_t* request_buf,
                                   uint8_t* response_buf,
                                   const ncsi_version_id_t* version_id) {
  ncsi_build_response_header(
      request_buf, response_buf, 0, 0,
      sizeof(ncsi_version_id_response_t) - sizeof(ncsi_header_t));
  ncsi_version_id_response_t* version_id_response =
      (ncsi_version_id_response_t*)response_buf;
  memcpy(&version_id_response->version, version_id, sizeof(ncsi_version_id_t));
  return sizeof(ncsi_version_id_response_t);
}

uint32_t ncsi_build_oem_get_mac_ack(const uint8_t* request_buf,
                                    uint8_t* response_buf,
                                    const mac_addr_t* mac) {
  ncsi_build_oem_ack(request_buf, response_buf,
                     sizeof(ncsi_host_mac_response_t));
  ncsi_host_mac_response_t* response = (ncsi_host_mac_response_t*)response_buf;
  memcpy(response->mac, mac->octet, MAC_ADDR_SIZE);
  return sizeof(ncsi_host_mac_response_t);
}

uint32_t ncsi_build_oem_simple_ack(const uint8_t* request_buf,
                                   uint8_t* response_buf) {
  ncsi_build_oem_ack(request_buf, response_buf,
                     sizeof(ncsi_oem_simple_response_t));
  return sizeof(ncsi_oem_simple_response_t);
}

uint32_t ncsi_build_oem_echo_ack(const uint8_t* request_buf,
                                 uint8_t* response_buf) {
  ncsi_oem_echo_response_t* echo_response =
      (ncsi_oem_echo_response_t*)response_buf;
  const ncsi_oem_echo_cmd_t* echo_cmd = (const ncsi_oem_echo_cmd_t*)request_buf;
  memmove(echo_response->pattern, echo_cmd->pattern, sizeof(echo_cmd->pattern));
  // Because we allow request and response to be the same buffer, it is
  // important that pattern copy precedes the call to ncsi_build_oem_ack.
  ncsi_build_oem_ack(request_buf, response_buf,
                     sizeof(ncsi_oem_echo_response_t));

  return sizeof(ncsi_oem_echo_response_t);
}

uint32_t ncsi_build_oem_get_filter_ack(const uint8_t* request_buf,
                                       uint8_t* response_buf,
                                       const ncsi_oem_filter_t* filter) {
  ncsi_build_oem_ack(request_buf, response_buf,
                     sizeof(ncsi_oem_get_filter_response_t));
  ncsi_oem_get_filter_response_t* get_filter_response =
      (ncsi_oem_get_filter_response_t*)response_buf;
  memcpy(&get_filter_response->filter, filter,
         sizeof(get_filter_response->filter));
  return sizeof(ncsi_oem_get_filter_response_t);
}

uint32_t ncsi_build_pt_stats_ack(const uint8_t* request_buf,
                                 uint8_t* response_buf,
                                 const ncsi_passthrough_stats_t* stats) {
  ncsi_build_response_header(
      request_buf, response_buf, 0, 0,
      sizeof(ncsi_passthrough_stats_response_t) - sizeof(ncsi_header_t));
  ncsi_passthrough_stats_response_t* pt_stats_response =
      (ncsi_passthrough_stats_response_t*)response_buf;
  /* TODO: endianness? */
  memcpy(&pt_stats_response->stats, stats, sizeof(pt_stats_response->stats));
  return sizeof(ncsi_passthrough_stats_response_t);
}

uint32_t ncsi_build_pt_stats_legacy_ack(
    const uint8_t* request_buf, uint8_t* response_buf,
    const ncsi_passthrough_stats_legacy_t* stats) {
  ncsi_build_response_header(
      request_buf, response_buf, 0, 0,
      sizeof(ncsi_passthrough_stats_legacy_response_t) - sizeof(ncsi_header_t));
  ncsi_passthrough_stats_legacy_response_t* pt_stats_response =
      (ncsi_passthrough_stats_legacy_response_t*)response_buf;
  /* TODO: endianness? */
  memcpy(&pt_stats_response->stats, stats, sizeof(pt_stats_response->stats));
  return sizeof(ncsi_passthrough_stats_legacy_response_t);
}

uint32_t ncsi_build_link_status_ack(const uint8_t* request_buf,
                                    uint8_t* response_buf,
                                    const ncsi_link_status_t* link_status) {
  ncsi_build_response_header(
      request_buf, response_buf, 0, 0,
      sizeof(ncsi_link_status_response_t) - sizeof(ncsi_header_t));
  ncsi_link_status_response_t* link_status_response =
      (ncsi_link_status_response_t*)response_buf;
  memcpy(&link_status_response->link_status, link_status,
         sizeof(link_status_response->link_status));
  return sizeof(ncsi_link_status_response_t);
}
